■ USB通信2(VC++)                                                          

  
   

■ PIC18F14K50 HIDクラス LED 点灯/消灯 制御・表示
<試作品仕様>
 ・PC(Windows)上のボタンスイッチ×4個をクリックすると PIC18F40K50のキバン上の対応するLEDがON/OFFすること
 ・PCとPIC間のUSB通信はHIDクラスとする。
 ・ボタンスイッチはLEDがONしているときは赤色、OFFの時は灰色とする。
 ・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと

 ★ ハード 及びPIC側のソフトは こちらを参照願います 

          

   <プログラム例>

//Form1.h


#pragma once
//Includes
#include <Windows.h>    //Definitions for various common and not so common types like DWORD, PCHAR, HANDLE, etc.
#include <setupapi.h>   //From Platform SDK. Definitions needed for the SetupDixxx() functions, which we use to
                                                //find our plug and play device.

//Modify this value to match the VID and PID in your USB device descriptor.
//Use the formatting: "Vid_xxxx&Pid_xxxx" where xxxx is a 16-bit hexadecimal number.
#define MY_DEVICE_ID  "Vid_04d8&Pid_003F"               //VID = 0x04D8  PID = 0x003F    


namespace CWhiteForm {

        using namespace System;
        using namespace System::ComponentModel;
        using namespace System::Collections;
        using namespace System::Windows::Forms;
        using namespace System::Data;
        using namespace System::Drawing;

        

//-------------------------------------------------------BEGIN CUT AND PASTE BLOCK--------------------------
        using namespace System::Runtime::InteropServices;  //Need this to support "unmanaged" code.

        /*
        In order to use these unmanaged functions from within the managed .NET environment, we need
        to explicitly import the functions which we will be using from other .DLL file(s).  Simply
        including the appropriate header files is not enough. 

        Note: In order to avoid potential name conflicts in the header files (which we still use),
        I have renamed the functions by adding "UM" (unmanaged) onto the end of them.  To find 
        documentation for the functions in MSDN, search for the function name without the extra 
        "UM" attached.
        Note2: In the header files (such as setupapi.h), normally the function names are 
        remapped, depending upon if UNICODE is defined or not.  For example, two versions of the
        function SetupDiGetDeviceInterfaceDetail() exist.  One for UNICODE, and one for ANSI.  
        If the wrong version of the function is called, things won't work correctly.  Therefore,
        in order to make sure the correct one gets called (based on your compiler settings, which
        may or may not define "UNICODE"), it is useful to explicity specify the CharSet when doing
        the DLL import.
        */

        #ifdef UNICODE
        #define Seeifdef        Unicode
        #else
        #define Seeifdef        Ansi
        #endif


        //使用するDLL関数の宣言
        //Returns a HDEVINFO type for a device information set (USB HID devices in
        //our case).  We will need the HDEVINFO as in input parameter for calling many of
        //the other SetupDixxx() functions.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetClassDevs", CallingConvention=CallingConvention::Winapi)]                
        extern "C" HDEVINFO  SetupDiGetClassDevsUM(
                LPGUID  ClassGuid,                                      //Input: Supply the class GUID here. 
                PCTSTR  Enumerator,                                     //Input: Use NULL here, not important for our purposes
                HWND  hwndParent,                                       //Input: Use NULL here, not important for our purposes
                DWORD  Flags);                                          //Input: Flags describing what kind of filtering to use.

        //Gives us "PSP_DEVICE_INTERFACE_DATA" which contains the Interface specific GUID (different
        //from class GUID).  We need the interface GUID to get the device path.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInterfaces", CallingConvention=CallingConvention::Winapi)]                                
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInterfacesUM(
                HDEVINFO  DeviceInfoSet,                        //Input: Give it the HDEVINFO we got from SetupDiGetClassDevs()
                PSP_DEVINFO_DATA  DeviceInfoData,       //Input (optional)
                LPGUID  InterfaceClassGuid,                     //Input 
                DWORD  MemberIndex,                                     //Input: "Index" of the device you are interested in getting the path for.
                PSP_DEVICE_INTERFACE_DATA  DeviceInterfaceData);//Output: This function fills in an "SP_DEVICE_INTERFACE_DATA" structure.

        //SetupDiDestroyDeviceInfoList() frees up memory by destroying a DeviceInfoList
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiDestroyDeviceInfoList", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiDestroyDeviceInfoListUM(                     
                HDEVINFO  DeviceInfoSet);                       //Input: Give it a handle to a device info list to deallocate from RAM.

        //SetupDiEnumDeviceInfo() fills in an "SP_DEVINFO_DATA" structure, which we need for SetupDiGetDeviceRegistryProperty()
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInfo", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInfoUM(
                HDEVINFO  DeviceInfoSet,
                DWORD  MemberIndex,
                PSP_DEVINFO_DATA  DeviceInfoData);

        //SetupDiGetDeviceRegistryProperty() gives us the hardware ID, which we use to check to see if it has matching VID/PID
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceRegistryProperty", CallingConvention=CallingConvention::Winapi)]
        extern "C"      WINSETUPAPI BOOL WINAPI  SetupDiGetDeviceRegistryPropertyUM(
                HDEVINFO  DeviceInfoSet,
                PSP_DEVINFO_DATA  DeviceInfoData,
                DWORD  Property,
                PDWORD  PropertyRegDataType,
                PBYTE  PropertyBuffer,   
                DWORD  PropertyBufferSize,  
                PDWORD  RequiredSize);

        //SetupDiGetDeviceInterfaceDetail() gives us a device path, which is needed before CreateFile() can be used.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceInterfaceDetail", CallingConvention=CallingConvention::Winapi)]
        extern "C" BOOL SetupDiGetDeviceInterfaceDetailUM(
                HDEVINFO DeviceInfoSet,                                                                         //Input: Wants HDEVINFO which can be obtained from SetupDiGetClassDevs()
                PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,                          //Input: Pointer to an structure which defines the device interface.  
                PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,     //Output: Pointer to a strucutre, which will contain the device path.
                DWORD DeviceInterfaceDetailDataSize,                                            //Input: Number of bytes to retrieve.
                PDWORD RequiredSize,                                                                            //Output (optional): Te number of bytes needed to hold the entire struct 
                PSP_DEVINFO_DATA DeviceInfoData);                                                       //Output


//  Variables that need to have wide scope.
        HANDLE WriteHandle = INVALID_HANDLE_VALUE;      //Need to get a write "handle" to our device before we can write to it.
        HANDLE ReadHandle = INVALID_HANDLE_VALUE;       //Need to get a read "handle" to our device before we can read from it.
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------

        
        //グローバル変数定義 
//      unsigned int ADCValue;
        int LedMode = 0,        //      LedMode = 0; 消灯 1:点灯
                Led1Mode = 0,   // Led1Mode = 0; 消灯 1:点灯
                Led2Mode = 0,   // Led2Mode = 0; 消灯 1:点灯
                Led3Mode = 0;   // Lee3Mode = 0; 消灯 1:点灯        

        DWORD BytesWritten = 0;
        DWORD BytesRead = 0;
        unsigned char OutputPacketBuffer[65];   //Allocate a memory buffer equal to our endpoint size + 1
        unsigned char InputPacketBuffer[65];


        /// <summary>
        /// Form1 の概要
        /// </summary>
        public ref class Form1 : public System::Windows::Forms::Form
        {
        public:
                Form1(void)     //コンストラクタ
                {
                        InitializeComponent();
                        //
                        //TODO: ここにコンストラクター コードを追加します
                        //
                }

        protected:
                /// <summary>
                /// 使用中のリソースをすべてクリーンアップします。
                /// </summary>
                ~Form1()        //デストラクタ
                {
                        if (components)
                        {
                                delete components;
                        }
                }

        private: System::Windows::Forms::Button^  ConnectBtn;
        private: System::Windows::Forms::Button^  LedSw;

        protected: 

        private: System::Windows::Forms::TextBox^  textBox1;
        private: System::Windows::Forms::Button^  LedSw1;
        private: System::Windows::Forms::Button^  LedSw2;
        private: System::Windows::Forms::Button^  LedSw3;






        private:
                /// <summary>
                /// 必要なデザイナー変数です。
                /// </summary>
                System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
                /// <summary>
                /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
                /// コード エディターで変更しないでください。
                /// </summary>
                void InitializeComponent(void)  //コンポーネントの初期化
                {
                        this->ConnectBtn = (gcnew System::Windows::Forms::Button());
                        this->LedSw = (gcnew System::Windows::Forms::Button());
                        this->textBox1 = (gcnew System::Windows::Forms::TextBox());
                        this->LedSw1 = (gcnew System::Windows::Forms::Button());
                        this->LedSw2 = (gcnew System::Windows::Forms::Button());
                        this->LedSw3 = (gcnew System::Windows::Forms::Button());
                        this->SuspendLayout();
                        // 
                        // ConnectBtn
                        // 
                        this->ConnectBtn->Location = System::Drawing::Point(35, 24);
                        this->ConnectBtn->Name = L"ConnectBtn";
                        this->ConnectBtn->Size = System::Drawing::Size(83, 33);
                        this->ConnectBtn->TabIndex = 0;
                        this->ConnectBtn->Text = L"接続";
                        this->ConnectBtn->UseVisualStyleBackColor = true;
                        this->ConnectBtn->Click += gcnew System::EventHandler(this, &Form1::ConnectBtn_Click);
                        // 
                        // LedSw
                        // 
                        this->LedSw->Location = System::Drawing::Point(35, 97);
                        this->LedSw->Name = L"LedSw";
                        this->LedSw->Size = System::Drawing::Size(75, 59);
                        this->LedSw->TabIndex = 1;
                        this->LedSw->Text = L"LED0";
                        this->LedSw->UseVisualStyleBackColor = true;
                        this->LedSw->Click += gcnew System::EventHandler(this, &Form1::LedSw_Click);
                        // 
                        // textBox1
                        // 
                        this->textBox1->Location = System::Drawing::Point(189, 35);
                        this->textBox1->Name = L"textBox1";
                        this->textBox1->Size = System::Drawing::Size(197, 22);
                        this->textBox1->TabIndex = 2;
                        // 
                        // LedSw1
                        // 
                        this->LedSw1->Location = System::Drawing::Point(147, 97);
                        this->LedSw1->Name = L"LedSw1";
                        this->LedSw1->Size = System::Drawing::Size(75, 59);
                        this->LedSw1->TabIndex = 3;
                        this->LedSw1->Text = L"LED1";
                        this->LedSw1->UseVisualStyleBackColor = true;
                        this->LedSw1->Click += gcnew System::EventHandler(this, &Form1::LedSw1_Click);
                        // 
                        // LedSw2
                        // 
                        this->LedSw2->Location = System::Drawing::Point(263, 97);
                        this->LedSw2->Name = L"LedSw2";
                        this->LedSw2->Size = System::Drawing::Size(75, 59);
                        this->LedSw2->TabIndex = 4;
                        this->LedSw2->Text = L"LED2";
                        this->LedSw2->UseVisualStyleBackColor = true;
                        this->LedSw2->Click += gcnew System::EventHandler(this, &Form1::LedSw2_Click);
                        // 
                        // LedSw3
                        // 
                        this->LedSw3->Location = System::Drawing::Point(379, 97);
                        this->LedSw3->Name = L"LedSw3";
                        this->LedSw3->Size = System::Drawing::Size(75, 59);
                        this->LedSw3->TabIndex = 5;
                        this->LedSw3->Text = L"LED3";
                        this->LedSw3->UseVisualStyleBackColor = true;
                        this->LedSw3->Click += gcnew System::EventHandler(this, &Form1::LedSw3_Click);
                        // 
                        // Form1
                        // 
                        this->AutoScaleDimensions = System::Drawing::SizeF(8, 15);
                        this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
                        this->ClientSize = System::Drawing::Size(498, 214);
                        this->Controls->Add(this->LedSw3);
                        this->Controls->Add(this->LedSw2);
                        this->Controls->Add(this->LedSw1);
                        this->Controls->Add(this->textBox1);
                        this->Controls->Add(this->LedSw);
                        this->Controls->Add(this->ConnectBtn);
                        this->Name = L"Form1";
                        this->Text = L"Form1";
                        this->ResumeLayout(false);
                        this->PerformLayout();

                }
#pragma endregion


        private: System::Void ConnectBtn_Click(System::Object^  sender, System::EventArgs^  e)  //USBパイプ接続
        {
                                 //-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
                /* 
                Before we can "connect" our application to our USB embedded device, we must first find the device.
                A USB bus can have many devices simultaneously connected, so somehow we have to find our device, and only
                our device.  This is done with the Vendor ID (VID) and Product ID (PID).  Each USB product line should have
                a unique combination of VID and PID.  

                Microsoft has created a number of functions which are useful for finding plug and play devices.  Documentation
                for each function used can be found in the MSDN library.  We will be using the following functions:

                SetupDiGetClassDevs()                                   //provided by setupapi.dll, which comes with Windows
                SetupDiEnumDeviceInterfaces()                   //provided by setupapi.dll, which comes with Windows
                GetLastError()                                                  //provided by kernel32.dll, which comes with Windows
                SetupDiDestroyDeviceInfoList()                  //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceInterfaceDetail()               //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceRegistryProperty()              //provided by setupapi.dll, which comes with Windows
                malloc()                                                                //part of C runtime library, msvcrt.dll?
                CreateFile()                                                    //provided by kernel32.dll, which comes with Windows

                We will also be using the following unusual data types and structures.  Documentation can also be found in
                the MSDN library:

                PSP_DEVICE_INTERFACE_DATA
                PSP_DEVICE_INTERFACE_DETAIL_DATA
                SP_DEVINFO_DATA
                HDEVINFO
                HANDLE
                GUID

                The ultimate objective of the following code is to call CreateFile(), which opens a communications
                pipe to a specific device (such as a HID class USB device endpoint).  CreateFile() returns a "handle" 
                which is needed later when calling ReadFile() or WriteFile().  These functions are used to actually 
                send and receive application related data to/from the USB peripheral device.

                However, in order to call CreateFile(), we first need to get the device path for the USB device
                with the correct VID and PID.  Getting the device path is a multi-step round about process, which
                requires calling several of the SetupDixxx() functions provided by setupapi.dll.
                */


                //Globally Unique Identifier (GUID) for HID class devices.  Windows uses GUIDs to identify things.
                GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}; 

                HDEVINFO DeviceInfoTable = INVALID_HANDLE_VALUE;
                PSP_DEVICE_INTERFACE_DATA InterfaceDataStructure = new SP_DEVICE_INTERFACE_DATA;
                PSP_DEVICE_INTERFACE_DETAIL_DATA DetailedInterfaceDataStructure = new SP_DEVICE_INTERFACE_DETAIL_DATA;
                SP_DEVINFO_DATA DevInfoData;

                DWORD InterfaceIndex = 0;
                DWORD StatusLastError = 0;
                DWORD dwRegType;
                DWORD dwRegSize;
                DWORD StructureSize = 0;
                PBYTE PropertyValueBuffer;
                bool MatchFound = false;
                DWORD ErrorStatus;

                String^ DeviceIDToFind = MY_DEVICE_ID;

                //First populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID. 
                DeviceInfoTable = SetupDiGetClassDevsUM(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

                //Now look through the list we just populated.  We are trying to see if any of them match our device. 
                while(true)
                {
                        InterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
                        if(SetupDiEnumDeviceInterfacesUM(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, InterfaceDataStructure))
                        {
                                ErrorStatus = GetLastError();
                                if(ERROR_NO_MORE_ITEMS == ErrorStatus)  //Did we reach the end of the list of matching devices in the DeviceInfoTable?
                                {       //Cound not find the device.  Must not have been attached.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                        }
                        else    //Else some other kind of unknown error ocurred...
                        {
                                ErrorStatus = GetLastError();
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return; 
                        }

                        //Now retrieve the hardware ID from the registry.  The hardware ID contains the VID and PID, which we will then 
                        //check to see if it is the correct device or not.

                        //Initialize an appropriate SP_DEVINFO_DATA structure.  We need this structure for SetupDiGetDeviceRegistryProperty().
                        DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
                        SetupDiEnumDeviceInfoUM(DeviceInfoTable, InterfaceIndex, &DevInfoData);

                        //First query for the size of the hardware ID, so we can know how big a buffer to allocate for the data.
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, NULL, 0, &dwRegSize);

                        //Allocate a buffer for the hardware ID.
                        PropertyValueBuffer = (BYTE *) malloc (dwRegSize);
                        if(PropertyValueBuffer == NULL) //if null, error, couldn't allocate enough memory
                        {       //Can't really recover from this situation, just exit instead.
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return;         
                        }

                        //Retrieve the hardware IDs for the current device we are looking at.  PropertyValueBuffer gets filled with a 
                        //REG_MULTI_SZ (array of null terminated strings).  To find a device, we only care about the very first string in the
                        //buffer, which will be the "device ID".  The device ID is a string which contains the VID and PID, in the example 
                        //format "Vid_04d8&Pid_003f".
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, PropertyValueBuffer, dwRegSize, NULL);

                        //Now check if the first string in the hardware ID matches the device ID of my USB device.
                        #ifdef UNICODE
                        String^ DeviceIDFromRegistry = gcnew String((wchar_t *)PropertyValueBuffer);
                        #else
                        String^ DeviceIDFromRegistry = gcnew String((char *)PropertyValueBuffer);
                        #endif

                        free(PropertyValueBuffer);              //No longer need the PropertyValueBuffer, free the memory to prevent potential memory leaks
                        textBox1->Text = "Searching Device!";
                        //Convert both strings to lower case.  This makes the code more robust/portable accross OS Versions
                        DeviceIDFromRegistry = DeviceIDFromRegistry->ToLowerInvariant();        
                        DeviceIDToFind = DeviceIDToFind->ToLowerInvariant();                            
                        //Now check if the hardware ID we are looking at contains the correct VID/PID
                        MatchFound = DeviceIDFromRegistry->Contains(DeviceIDToFind);            
                        if(MatchFound == true)
                        {
                                //Device must have been found.  Open read and write handles.  In order to do this, we will need the actual device path first.
                                //We can get the path by calling SetupDiGetDeviceInterfaceDetail(), however, we have to call this function twice:  The first
                                //time to get the size of the required structure/buffer to hold the detailed interface data, then a second time to actually 
                                //get the structure (after we have allocated enough memory for the structure.)
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                //First call populates "StructureSize" with the correct value
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL);   
                                DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize));             //Allocate enough memory
                                if(DetailedInterfaceDataStructure == NULL)      //if null, error, couldn't allocate enough memory
                                {       //Can't really recover from this situation, just exit instead.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                 //Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods.  
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); 

                                //We now have the proper device path, and we can finally open read and write handles to the device.
                                //We store the handles in the global variables "WriteHandle" and "ReadHandle", which we will use later to actually communicate.
                                WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);

                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                        textBox1->Text = "Write Enabled.";                              //Make button no longer greyed out
                                ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                {
                                        textBox1->Text = "Read Enabled.";                                       //Make label no longer greyed out
                                }
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                               
                                //追加修正部
                                // 接続確認メッセージ準備 
                                OutputPacketBuffer[0] = 0;                                                      // Report ID  
                                OutputPacketBuffer[1] = 0x30;                                           // 接続確認 
                                // 接続確認 コマンド送信
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                // OK受信
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                                // OK確認 
                                if((InputPacketBuffer[3] == 0x4F)&&(InputPacketBuffer[4] == 0x4B))
                                        textBox1->Text = "接続完了!!";                              // 接続正常完了
                                // 接続完了でタイマ1スタート
//                              timer1->Interval = 1000;
//                              timer1->Enabled = TRUE;
                                return;
                        }

                        InterfaceIndex++;       
                        //Keep looping until we either find a device with matching VID and PID, or until we run out of items.
                }//end of while(true)   
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------

        }



        private: System::Void LedSw_Click(System::Object^  sender, System::EventArgs^  e) 
        {
                                
                OutputPacketBuffer[0] = 0;                                      // Report ID  
                OutputPacketBuffer[1] = 0x31;                           // LED制御コマンド

                OutputPacketBuffer[2] = 0x31;                           // LED0アドレス

                if(LedMode == 0)        //消灯していたなら
                {
                        LedMode = 1;
                        OutputPacketBuffer[3] = 0x31;                   // Led点灯        //0x31 = '1'
                }
                else
                {
                        LedMode = 0;
                        OutputPacketBuffer[3] = 0x30;                   // Led消灯        //0x30 = '0'
                }

                // 送信
                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);


                // 受信
                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                if(InputPacketBuffer[3] == 0x31)LedSw->BackColor =Color:: Red;          // オンなら赤
                else LedSw->BackColor = Color::Gray;            // オフなら緑
        }
        
private: System::Void LedSw1_Click(System::Object^  sender, System::EventArgs^  e)
                 {
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x31;                           // LED制御コマンド
                        OutputPacketBuffer[2] = 0x32;                           // LED1アドレス
                        if(Led1Mode == 0)       //消灯していたなら
                        {
                                Led1Mode = 1;
                                OutputPacketBuffer[3] = 0x31;                   // Led点灯
                        }
                        else
                        {
                                Led1Mode = 0;
                                OutputPacketBuffer[3] = 0x30;                   // Led消灯
                        }

                        // 送信
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);


                        // 受信
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                        if(InputPacketBuffer[3] == 0x31)LedSw1->BackColor =Color:: Red;         // オンなら赤
                        else LedSw1->BackColor = Color::Gray;           // オフなら緑
                 }

private: System::Void LedSw2_Click(System::Object^  sender, System::EventArgs^  e)
                 {
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x31;                           // LED制御コマンド
                        OutputPacketBuffer[2] = 0x33;                           // LED2アドレス
                        if(Led2Mode == 0)       //消灯していたなら
                        {
                                Led2Mode = 1;
                                OutputPacketBuffer[3] = 0x31;                   // Led点灯
                        }
                        else
                        {
                                Led2Mode = 0;
                                OutputPacketBuffer[3] = 0x30;                   // Led消灯
                        }

                        // 送信
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);


                        // 受信
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                        if(InputPacketBuffer[3] == 0x31)LedSw2->BackColor =Color:: Red;         // オンなら赤
                        else LedSw2->BackColor = Color::Gray;           // オフなら緑
                        

                 }

private: System::Void LedSw3_Click(System::Object^  sender, System::EventArgs^  e)
                 {
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x31;                           // LED制御コマンド
                        OutputPacketBuffer[2] = 0x34;                           // LED2アドレス
                        if(Led3Mode == 0)       //消灯していたなら
                        {
                                Led3Mode = 1;
                                OutputPacketBuffer[3] = 0x31;                   // Led点灯
                        }
                        else
                        {
                                Led3Mode = 0;
                                OutputPacketBuffer[3] = 0x30;                   // Led消灯
                        }

                        // 送信
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);


                        // 受信
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                        if(InputPacketBuffer[3] == 0x31)LedSw3->BackColor =Color:: Red;         // オンなら赤
                        else LedSw3->BackColor = Color::Gray;           // オフなら緑


                 }

};//end of class Form1
} 

<実行結果>

 接続ボタンをクリックした後、LED0、LED2、LED3を点灯させたところです。
尚、PIC18F14K50のキバン上には本テーマと関係ない部品が多々搭載されています。





■ PIC18F14K50 HIDクラス スイッチの状態 & 電圧読込

<試作品仕様>
 ・PIC18F14K50のキバン上のスイッチ×3個を押すと PC(Windows)上の対応するovalShape×3個の色が 灰色→オレンジ色に変わること
 ・PCとPIC間のUSB通信はHIDクラスとする。
 ・可変抵抗器×3個により設定される電圧をPIC18F14K50の内蔵ADコンバータで読込、この電圧値[V]をPC上の対応するテキストボックス×3個に表示のこと。
 ・テキストボックスに表示される電圧[V]は、小数点以下2桁とする。
 ・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと

 ★ ハード 及びPIC側のソフトは こちらを参照願います 


          

   <プログラム例>

#pragma once
//Includes
#include <Windows.h>    //Definitions for various common and not so common types like DWORD, PCHAR, HANDLE, etc.
#include <setupapi.h>   //From Platform SDK. Definitions needed for the SetupDixxx() functions, which we use to
                                                //find our plug and play device.

//Modify this value to match the VID and PID in your USB device descriptor.
//Use the formatting: "Vid_xxxx&Pid_xxxx" where xxxx is a 16-bit hexadecimal number.
#define MY_DEVICE_ID  "Vid_04d8&Pid_003F"       


namespace CWhiteForm {

        using namespace System;
        using namespace System::ComponentModel;
        using namespace System::Collections;
        using namespace System::Windows::Forms;
        using namespace System::Data;
        using namespace System::Drawing;

//-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
        using namespace System::Runtime::InteropServices;  //Need this to support "unmanaged" code.

        /*
        In order to use these unmanaged functions from within the managed .NET environment, we need
        to explicitly import the functions which we will be using from other .DLL file(s).  Simply
        including the appropriate header files is not enough. 

        Note: In order to avoid potential name conflicts in the header files (which we still use),
        I have renamed the functions by adding "UM" (unmanaged) onto the end of them.  To find 
        documentation for the functions in MSDN, search for the function name without the extra 
        "UM" attached.
        Note2: In the header files (such as setupapi.h), normally the function names are 
        remapped, depending upon if UNICODE is defined or not.  For example, two versions of the
        function SetupDiGetDeviceInterfaceDetail() exist.  One for UNICODE, and one for ANSI.  
        If the wrong version of the function is called, things won't work correctly.  Therefore,
        in order to make sure the correct one gets called (based on your compiler settings, which
        may or may not define "UNICODE"), it is useful to explicity specify the CharSet when doing
        the DLL import.
        */

        #ifdef UNICODE
        #define Seeifdef        Unicode
        #else
        #define Seeifdef        Ansi
        #endif

        //Returns a HDEVINFO type for a device information set (USB HID devices in
        //our case).  We will need the HDEVINFO as in input parameter for calling many of
        //the other SetupDixxx() functions.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetClassDevs", CallingConvention=CallingConvention::Winapi)]                
        extern "C" HDEVINFO  SetupDiGetClassDevsUM(
                LPGUID  ClassGuid,                                      //Input: Supply the class GUID here. 
                PCTSTR  Enumerator,                                     //Input: Use NULL here, not important for our purposes
                HWND  hwndParent,                                       //Input: Use NULL here, not important for our purposes
                DWORD  Flags);                                          //Input: Flags describing what kind of filtering to use.

        //Gives us "PSP_DEVICE_INTERFACE_DATA" which contains the Interface specific GUID (different
        //from class GUID).  We need the interface GUID to get the device path.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInterfaces", CallingConvention=CallingConvention::Winapi)]                                
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInterfacesUM(
                HDEVINFO  DeviceInfoSet,                        //Input: Give it the HDEVINFO we got from SetupDiGetClassDevs()
                PSP_DEVINFO_DATA  DeviceInfoData,       //Input (optional)
                LPGUID  InterfaceClassGuid,                     //Input 
                DWORD  MemberIndex,                                     //Input: "Index" of the device you are interested in getting the path for.
                PSP_DEVICE_INTERFACE_DATA  DeviceInterfaceData);//Output: This function fills in an "SP_DEVICE_INTERFACE_DATA" structure.

        //SetupDiDestroyDeviceInfoList() frees up memory by destroying a DeviceInfoList
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiDestroyDeviceInfoList", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiDestroyDeviceInfoListUM(                     
                HDEVINFO  DeviceInfoSet);                       //Input: Give it a handle to a device info list to deallocate from RAM.

        //SetupDiEnumDeviceInfo() fills in an "SP_DEVINFO_DATA" structure, which we need for SetupDiGetDeviceRegistryProperty()
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInfo", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInfoUM(
                HDEVINFO  DeviceInfoSet,
                DWORD  MemberIndex,
                PSP_DEVINFO_DATA  DeviceInfoData);

        //SetupDiGetDeviceRegistryProperty() gives us the hardware ID, which we use to check to see if it has matching VID/PID
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceRegistryProperty", CallingConvention=CallingConvention::Winapi)]
        extern "C"      WINSETUPAPI BOOL WINAPI  SetupDiGetDeviceRegistryPropertyUM(
                HDEVINFO  DeviceInfoSet,
                PSP_DEVINFO_DATA  DeviceInfoData,
                DWORD  Property,
                PDWORD  PropertyRegDataType,
                PBYTE  PropertyBuffer,   
                DWORD  PropertyBufferSize,  
                PDWORD  RequiredSize);

        //SetupDiGetDeviceInterfaceDetail() gives us a device path, which is needed before CreateFile() can be used.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceInterfaceDetail", CallingConvention=CallingConvention::Winapi)]
        extern "C" BOOL SetupDiGetDeviceInterfaceDetailUM(
                HDEVINFO DeviceInfoSet,                                                                         //Input: Wants HDEVINFO which can be obtained from SetupDiGetClassDevs()
                PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,                          //Input: Pointer to an structure which defines the device interface.  
                PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,     //Output: Pointer to a strucutre, which will contain the device path.
                DWORD DeviceInterfaceDetailDataSize,                                            //Input: Number of bytes to retrieve.
                PDWORD RequiredSize,                                                                            //Output (optional): Te number of bytes needed to hold the entire struct 
                PSP_DEVINFO_DATA DeviceInfoData);                                                       //Output


//  Variables that need to have wide scope.
        HANDLE WriteHandle = INVALID_HANDLE_VALUE;      //Need to get a write "handle" to our device before we can write to it.
        HANDLE ReadHandle = INVALID_HANDLE_VALUE;       //Need to get a read "handle" to our device before we can read from it.
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------


        //グローバル変数定義 
        unsigned int ADCValue;
        DWORD BytesWritten = 0;
        DWORD BytesRead = 0;
        unsigned char OutputPacketBuffer[65];   //Allocate a memory buffer equal to our endpoint size + 1
        unsigned char InputPacketBuffer[65];

        /// <summary>
        /// Form1 の概要
        /// </summary>
        public ref class Form1 : public System::Windows::Forms::Form
        {
        public:
                Form1(void)
                {
                        InitializeComponent();  //
                //      ovalShape1->FillStyle = FillStyle.Solid;        //サポートされていない    //プロパティでFillStyle = Solidを設定する
                                                                                                                //C#のovalShape1.FillStyle = FillStyle.Solid;はサポートされている
                        

                        ovalShape1->FillColor = Color::Gray;    //灰色で塗りつぶし
                        ovalShape2->FillColor = Color::Gray;
                        ovalShape3->FillColor = Color::Gray;
                }

        protected:
                /// <summary>
                /// 使用中のリソースをすべてクリーンアップします。
                /// </summary>
                ~Form1()
                {
                        if (components)
                        {
                                delete components;
                        }
                }
        private: System::Windows::Forms::Button^  ConnectBtn;
        protected: 

        protected: 
        private: System::Windows::Forms::Label^  label1;
        private: System::Windows::Forms::TextBox^  textBox1;
        private: System::Windows::Forms::TextBox^  textBox2;
        private: System::Windows::Forms::Timer^  timer1;
        private: Microsoft::VisualBasic::PowerPacks::ShapeContainer^  shapeContainer1;
        private: Microsoft::VisualBasic::PowerPacks::OvalShape^  ovalShape3;
        private: Microsoft::VisualBasic::PowerPacks::OvalShape^  ovalShape2;
        private: Microsoft::VisualBasic::PowerPacks::OvalShape^  ovalShape1;
        private: System::Windows::Forms::Label^  label2;
        private: System::Windows::Forms::Label^  label3;
        private: System::Windows::Forms::TextBox^  textBox3;
        private: System::Windows::Forms::TextBox^  textBox4;
        private: System::Windows::Forms::Label^  label4;
        private: System::Windows::Forms::Label^  label5;
        private: System::Windows::Forms::Label^  label6;
        private: System::ComponentModel::IContainer^  components;

        private:
                /// <summary>
                /// 必要なデザイナー変数です。
                /// </summary>


#pragma region Windows Form Designer generated code
                /// <summary>
                /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
                /// コード エディターで変更しないでください。
                /// </summary>
                void InitializeComponent(void)
                {
                        this->components = (gcnew System::ComponentModel::Container());
                        this->ConnectBtn = (gcnew System::Windows::Forms::Button());
                        this->label1 = (gcnew System::Windows::Forms::Label());
                        this->textBox1 = (gcnew System::Windows::Forms::TextBox());
                        this->textBox2 = (gcnew System::Windows::Forms::TextBox());
                        this->timer1 = (gcnew System::Windows::Forms::Timer(this->components));
                        this->shapeContainer1 = (gcnew Microsoft::VisualBasic::PowerPacks::ShapeContainer());
                        this->ovalShape3 = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape());
                        this->ovalShape2 = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape());
                        this->ovalShape1 = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape());
                        this->label2 = (gcnew System::Windows::Forms::Label());
                        this->label3 = (gcnew System::Windows::Forms::Label());
                        this->textBox3 = (gcnew System::Windows::Forms::TextBox());
                        this->textBox4 = (gcnew System::Windows::Forms::TextBox());
                        this->label4 = (gcnew System::Windows::Forms::Label());
                        this->label5 = (gcnew System::Windows::Forms::Label());
                        this->label6 = (gcnew System::Windows::Forms::Label());
                        this->SuspendLayout();
                        // 
                        // ConnectBtn
                        // 
                        this->ConnectBtn->Location = System::Drawing::Point(24, 27);
                        this->ConnectBtn->Name = L"ConnectBtn";
                        this->ConnectBtn->Size = System::Drawing::Size(88, 40);
                        this->ConnectBtn->TabIndex = 0;
                        this->ConnectBtn->Text = L"接続";
                        this->ConnectBtn->UseVisualStyleBackColor = true;
                        this->ConnectBtn->Click += gcnew System::EventHandler(this, &Form1::ConnectBtn_Click);
                        // 
                        // label1
                        // 
                        this->label1->AutoSize = true;
                        this->label1->Location = System::Drawing::Point(77, 176);
                        this->label1->Name = L"label1";
                        this->label1->Size = System::Drawing::Size(35, 15);
                        this->label1->TabIndex = 1;
                        this->label1->Text = L"SW1";
                        // 
                        // textBox1
                        // 
                        this->textBox1->Location = System::Drawing::Point(152, 37);
                        this->textBox1->Name = L"textBox1";
                        this->textBox1->Size = System::Drawing::Size(100, 22);
                        this->textBox1->TabIndex = 2;
                        // 
                        // textBox2
                        // 
                        this->textBox2->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 13.8F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
                                static_cast<System::Byte>(128)));
                        this->textBox2->Location = System::Drawing::Point(43, 224);
                        this->textBox2->Name = L"textBox2";
                        this->textBox2->Size = System::Drawing::Size(100, 30);
                        this->textBox2->TabIndex = 3;
                        // 
                        // timer1
                        // 
                        this->timer1->Tick += gcnew System::EventHandler(this, &Form1::timer1_Tick);
                        // 
                        // shapeContainer1
                        // 
                        this->shapeContainer1->Location = System::Drawing::Point(0, 0);
                        this->shapeContainer1->Margin = System::Windows::Forms::Padding(0);
                        this->shapeContainer1->Name = L"shapeContainer1";
                        this->shapeContainer1->Shapes->AddRange(gcnew cli::array< Microsoft::VisualBasic::PowerPacks::Shape^  >(3) {this->ovalShape3, 
                                this->ovalShape2, this->ovalShape1});
                        this->shapeContainer1->Size = System::Drawing::Size(526, 313);
                        this->shapeContainer1->TabIndex = 4;
                        this->shapeContainer1->TabStop = false;
                        // 
                        // ovalShape3
                        // 
                        this->ovalShape3->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid;
                        this->ovalShape3->Location = System::Drawing::Point(393, 95);
                        this->ovalShape3->Name = L"ovalShape3";
                        this->ovalShape3->Size = System::Drawing::Size(65, 65);
                        // 
                        // ovalShape2
                        // 
                        this->ovalShape2->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid;
                        this->ovalShape2->Location = System::Drawing::Point(235, 97);
                        this->ovalShape2->Name = L"ovalShape2";
                        this->ovalShape2->Size = System::Drawing::Size(65, 65);
                        // 
                        // ovalShape1
                        // 
                        this->ovalShape1->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid;
                        this->ovalShape1->Location = System::Drawing::Point(55, 94);
                        this->ovalShape1->Name = L"ovalShape1";
                        this->ovalShape1->Size = System::Drawing::Size(65, 65);
                        // 
                        // label2
                        // 
                        this->label2->AutoSize = true;
                        this->label2->Location = System::Drawing::Point(256, 176);
                        this->label2->Name = L"label2";
                        this->label2->Size = System::Drawing::Size(35, 15);
                        this->label2->TabIndex = 5;
                        this->label2->Text = L"SW2";
                        // 
                        // label3
                        // 
                        this->label3->AutoSize = true;
                        this->label3->Location = System::Drawing::Point(408, 176);
                        this->label3->Name = L"label3";
                        this->label3->Size = System::Drawing::Size(35, 15);
                        this->label3->TabIndex = 6;
                        this->label3->Text = L"SW3";
                        // 
                        // textBox3
                        // 
                        this->textBox3->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 13.8F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
                                static_cast<System::Byte>(128)));
                        this->textBox3->Location = System::Drawing::Point(213, 224);
                        this->textBox3->Name = L"textBox3";
                        this->textBox3->Size = System::Drawing::Size(100, 30);
                        this->textBox3->TabIndex = 7;
                        // 
                        // textBox4
                        // 
                        this->textBox4->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 13.8F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
                                static_cast<System::Byte>(128)));
                        this->textBox4->Location = System::Drawing::Point(387, 224);
                        this->textBox4->Name = L"textBox4";
                        this->textBox4->Size = System::Drawing::Size(100, 30);
                        this->textBox4->TabIndex = 8;
                        // 
                        // label4
                        // 
                        this->label4->AutoSize = true;
                        this->label4->Location = System::Drawing::Point(79, 269);
                        this->label4->Name = L"label4";
                        this->label4->Size = System::Drawing::Size(33, 15);
                        this->label4->TabIndex = 9;
                        this->label4->Text = L"VR1";
                        // 
                        // label5
                        // 
                        this->label5->AutoSize = true;
                        this->label5->Location = System::Drawing::Point(256, 269);
                        this->label5->Name = L"label5";
                        this->label5->Size = System::Drawing::Size(33, 15);
                        this->label5->TabIndex = 10;
                        this->label5->Text = L"VR2";
                        // 
                        // label6
                        // 
                        this->label6->AutoSize = true;
                        this->label6->Location = System::Drawing::Point(422, 269);
                        this->label6->Name = L"label6";
                        this->label6->Size = System::Drawing::Size(33, 15);
                        this->label6->TabIndex = 11;
                        this->label6->Text = L"VR3";
                        // 
                        // Form1
                        // 
                        this->AutoScaleDimensions = System::Drawing::SizeF(8, 15);
                        this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
                        this->ClientSize = System::Drawing::Size(526, 313);
                        this->Controls->Add(this->label6);
                        this->Controls->Add(this->label5);
                        this->Controls->Add(this->label4);
                        this->Controls->Add(this->textBox4);
                        this->Controls->Add(this->textBox3);
                        this->Controls->Add(this->label3);
                        this->Controls->Add(this->label2);
                        this->Controls->Add(this->textBox2);
                        this->Controls->Add(this->textBox1);
                        this->Controls->Add(this->label1);
                        this->Controls->Add(this->ConnectBtn);
                        this->Controls->Add(this->shapeContainer1);
                        this->Name = L"Form1";
                        this->Text = L"Form1";
                        this->ResumeLayout(false);
                        this->PerformLayout();

                }
#pragma endregion
        private: System::Void ConnectBtn_Click(System::Object^  sender, System::EventArgs^  e) 
                         {
                                 
//-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
                /* 
                Before we can "connect" our application to our USB embedded device, we must first find the device.
                A USB bus can have many devices simultaneously connected, so somehow we have to find our device, and only
                our device.  This is done with the Vendor ID (VID) and Product ID (PID).  Each USB product line should have
                a unique combination of VID and PID.  

                Microsoft has created a number of functions which are useful for finding plug and play devices.  Documentation
                for each function used can be found in the MSDN library.  We will be using the following functions:

                SetupDiGetClassDevs()                                   //provided by setupapi.dll, which comes with Windows
                SetupDiEnumDeviceInterfaces()                   //provided by setupapi.dll, which comes with Windows
                GetLastError()                                                  //provided by kernel32.dll, which comes with Windows
                SetupDiDestroyDeviceInfoList()                  //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceInterfaceDetail()               //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceRegistryProperty()              //provided by setupapi.dll, which comes with Windows
                malloc()                                                                //part of C runtime library, msvcrt.dll?
                CreateFile()                                                    //provided by kernel32.dll, which comes with Windows

                We will also be using the following unusual data types and structures.  Documentation can also be found in
                the MSDN library:

                PSP_DEVICE_INTERFACE_DATA
                PSP_DEVICE_INTERFACE_DETAIL_DATA
                SP_DEVINFO_DATA
                HDEVINFO
                HANDLE
                GUID

                The ultimate objective of the following code is to call CreateFile(), which opens a communications
                pipe to a specific device (such as a HID class USB device endpoint).  CreateFile() returns a "handle" 
                which is needed later when calling ReadFile() or WriteFile().  These functions are used to actually 
                send and receive application related data to/from the USB peripheral device.

                However, in order to call CreateFile(), we first need to get the device path for the USB device
                with the correct VID and PID.  Getting the device path is a multi-step round about process, which
                requires calling several of the SetupDixxx() functions provided by setupapi.dll.
                */


                //Globally Unique Identifier (GUID) for HID class devices.  Windows uses GUIDs to identify things.
                GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}; 

                HDEVINFO DeviceInfoTable = INVALID_HANDLE_VALUE;
                PSP_DEVICE_INTERFACE_DATA InterfaceDataStructure = new SP_DEVICE_INTERFACE_DATA;
                PSP_DEVICE_INTERFACE_DETAIL_DATA DetailedInterfaceDataStructure = new SP_DEVICE_INTERFACE_DETAIL_DATA;
                SP_DEVINFO_DATA DevInfoData;

                DWORD InterfaceIndex = 0;
                DWORD StatusLastError = 0;
                DWORD dwRegType;
                DWORD dwRegSize;
                DWORD StructureSize = 0;
                PBYTE PropertyValueBuffer;
                bool MatchFound = false;
                DWORD ErrorStatus;

                String^ DeviceIDToFind = MY_DEVICE_ID;

                //First populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID. 
                DeviceInfoTable = SetupDiGetClassDevsUM(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

                //Now look through the list we just populated.  We are trying to see if any of them match our device. 
                while(true)
                {
                        InterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
                        if(SetupDiEnumDeviceInterfacesUM(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, InterfaceDataStructure))
                        {
                                ErrorStatus = GetLastError();
                                if(ERROR_NO_MORE_ITEMS == ErrorStatus)  //Did we reach the end of the list of matching devices in the DeviceInfoTable?
                                {       //Cound not find the device.  Must not have been attached.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                        }
                        else    //Else some other kind of unknown error ocurred...
                        {
                                ErrorStatus = GetLastError();
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return; 
                        }

                        //Now retrieve the hardware ID from the registry.  The hardware ID contains the VID and PID, which we will then 
                        //check to see if it is the correct device or not.

                        //Initialize an appropriate SP_DEVINFO_DATA structure.  We need this structure for SetupDiGetDeviceRegistryProperty().
                        DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
                        SetupDiEnumDeviceInfoUM(DeviceInfoTable, InterfaceIndex, &DevInfoData);

                        //First query for the size of the hardware ID, so we can know how big a buffer to allocate for the data.
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, NULL, 0, &dwRegSize);

                        //Allocate a buffer for the hardware ID.
                        PropertyValueBuffer = (BYTE *) malloc (dwRegSize);
                        if(PropertyValueBuffer == NULL) //if null, error, couldn't allocate enough memory
                        {       //Can't really recover from this situation, just exit instead.
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return;         
                        }

                        //Retrieve the hardware IDs for the current device we are looking at.  PropertyValueBuffer gets filled with a 
                        //REG_MULTI_SZ (array of null terminated strings).  To find a device, we only care about the very first string in the
                        //buffer, which will be the "device ID".  The device ID is a string which contains the VID and PID, in the example 
                        //format "Vid_04d8&Pid_003f".
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, PropertyValueBuffer, dwRegSize, NULL);

                        //Now check if the first string in the hardware ID matches the device ID of my USB device.
                        #ifdef UNICODE
                        String^ DeviceIDFromRegistry = gcnew String((wchar_t *)PropertyValueBuffer);
                        #else
                        String^ DeviceIDFromRegistry = gcnew String((char *)PropertyValueBuffer);
                        #endif

                        free(PropertyValueBuffer);              //No longer need the PropertyValueBuffer, free the memory to prevent potential memory leaks
                        textBox1->Text = "Searching Device!";
                        //Convert both strings to lower case.  This makes the code more robust/portable accross OS Versions
                        DeviceIDFromRegistry = DeviceIDFromRegistry->ToLowerInvariant();        
                        DeviceIDToFind = DeviceIDToFind->ToLowerInvariant();                            
                        //Now check if the hardware ID we are looking at contains the correct VID/PID
                        MatchFound = DeviceIDFromRegistry->Contains(DeviceIDToFind);            
                        if(MatchFound == true)
                        {
                                //Device must have been found.  Open read and write handles.  In order to do this, we will need the actual device path first.
                                //We can get the path by calling SetupDiGetDeviceInterfaceDetail(), however, we have to call this function twice:  The first
                                //time to get the size of the required structure/buffer to hold the detailed interface data, then a second time to actually 
                                //get the structure (after we have allocated enough memory for the structure.)
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                //First call populates "StructureSize" with the correct value
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL);   
                                DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize));             //Allocate enough memory
                                if(DetailedInterfaceDataStructure == NULL)      //if null, error, couldn't allocate enough memory
                                {       //Can't really recover from this situation, just exit instead.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                 //Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods.  
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); 

                                //We now have the proper device path, and we can finally open read and write handles to the device.
                                //We store the handles in the global variables "WriteHandle" and "ReadHandle", which we will use later to actually communicate.
                                WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);

                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                        textBox1->Text = "Write Enabled.";                              //Make button no longer greyed out
                                ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                {
                                        textBox1->Text = "Read Enabled.";                                       //Make label no longer greyed out
                                }
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                               
                                //追加修正部
                                OutputPacketBuffer[0] = 0;                                                      // Report ID  
                                OutputPacketBuffer[1] = 0x30;                                           // 接続確認 
                                
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                if((InputPacketBuffer[3] == 0x4F)&&(InputPacketBuffer[4] == 0x4B))
                                        textBox1->Text = "接続完了!";                               // 接続正常完了

                                //タイマ1スタート
                                timer1->Interval = 100; //インターバル時間:100msec
                                timer1->Enabled = TRUE;
                                return;
                        }

                        InterfaceIndex++;       
                        //Keep looping until we either find a device with matching VID and PID, or until we run out of items.
                }//end of while(true)   
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------


                         }

        private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e)       //インターバルタイマ     //100msec
                         {

                                unsigned int ADCValue;
                                double Volt;

                                //可変抵抗器出力電圧のAD変換値 読込
                
                                OutputPacketBuffer[0] = 0;                                      // Report ID  
                                OutputPacketBuffer[1] = 0x33;                           // 可変抵抗器outのAD変換値読込


                                OutputPacketBuffer[2] = 0x31;                           // VR1
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                                ADCValue = (InputPacketBuffer[4] * 256) + InputPacketBuffer[3];
                                Volt = (ADCValue * 5.0) / 1024;
                                textBox2->Text = String::Format("{0:F2} [V]",Volt);             //小数点以下2桁にして表示


                                OutputPacketBuffer[2] = 0x32;                           // VR2
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                                ADCValue = (InputPacketBuffer[4] * 256) + InputPacketBuffer[3];
                                Volt = (ADCValue * 5.0) / 1024;
                                textBox3->Text = String::Format("{0:F2} [V]",Volt);             //小数点以下2桁にして表示


                
                                OutputPacketBuffer[2] = 0x33;                           // VR3
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);      
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                                ADCValue = (InputPacketBuffer[4] * 256) + InputPacketBuffer[3];
                                Volt = (ADCValue * 5.0) / 1024;
                                textBox4->Text = String::Format("{0:F2} [V]",Volt);             //小数点以下2桁にして表示


                                //スイッチの状態読込
                                
                                OutputPacketBuffer[0] = 0;                                      // Report ID  
                                OutputPacketBuffer[1] = 0x32;                           // SW状態要求コマンド

                                OutputPacketBuffer[2] = 0x31;                           // SW1
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                if(InputPacketBuffer[3] == 0x30)                        // オンか? 
                                        ovalShape1->FillColor = Color::Orange;  //ON ならオレンジ色
                                else
                                        ovalShape1->FillColor = Color::Gray;            // OFFなら灰色


                                OutputPacketBuffer[2] = 0x32;                           // SW2
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                if(InputPacketBuffer[3] == 0x30)                        // オンか? 
                                        ovalShape2->FillColor = Color::Orange;  //ON ならオレンジ色
                                else
                                        ovalShape2->FillColor = Color::Gray;            // OFFなら灰色



                                
                                OutputPacketBuffer[2] = 0x33;                           // SW3
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                if(InputPacketBuffer[3] == 0x30)                        // オンか? 
                                        ovalShape3->FillColor = Color::Orange;  //ON ならオレンジ色
                                else
                                        ovalShape3->FillColor = Color::Gray;            // OFFなら灰色






                        }

                
};
}

 


<実行結果>
 ・接続ボタンをクリックしてUSB接続をした後に スイッチボタンSW1とSW3を押した時のPCのフォーム画面です。
 ・ovalShapeがオレンジ色になっているスイッチはON状態をあらわし、灰色はOFF状態の場合です。
 ・テキストボックスに表示されている値は、PIC18F14K50が読み込んだ電圧値で、小数点以下2桁で表示されています。

  









 PIC32MX795F512L HIDクラス LED点灯/消灯、ADコンバータ読込・表示
 <試作品仕様>
  ・PCとPIC間のUSB通信はHIDクラスとする。
  ・PC(Windows)上のボタンスイッチ×4個をクリックすると PIC32MX795F512Lのキバン上の対応するLEDがON/OFFすること
  ・PCとPIC間のUSB通信はHIDクラスとする。
  ・ボタンスイッチはLEDがONしているときは赤色、OFFの時は灰色とする。
  ・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと
  ・PIC32MX795F512Lのキバン上のスイッチ×3個を押すと PC(Windows)上の対応するovalShape×3個の色が 灰色→オレンジ色に変わること
  ・可変抵抗器により設定される電圧をPIC32MX795F512L内蔵ADコンバータで読込、この電圧値[V]をPC上のテキストボックスに表示のこと。
  ・テキストボックスに表示される電圧[V]は、小数点以下2桁とする。
  ・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと

 ★ PIC側のハードとソフトは こちらを参照願います 
        

     

          

   <プログラム例>

//Form1.h


#pragma once
//Includes
#include <Windows.h>    //Definitions for various common and not so common types like DWORD, PCHAR, HANDLE, etc.
#include <setupapi.h>   //From Platform SDK. Definitions needed for the SetupDixxx() functions, which we use to
                                                //find our plug and play device.

//Modify this value to match the VID and PID in your USB device descriptor.
//Use the formatting: "Vid_xxxx&Pid_xxxx" where xxxx is a 16-bit hexadecimal number.
#define MY_DEVICE_ID  "Vid_04d8&Pid_003F"               //VID = 0x04D8  PID = 0x003F    





namespace CWhiteForm {

        using namespace System;
        using namespace System::ComponentModel;
        using namespace System::Collections;
        using namespace System::Windows::Forms;
        using namespace System::Data;
        using namespace System::Drawing;


//-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
        using namespace System::Runtime::InteropServices;  //Need this to support "unmanaged" code.

        /*
        In order to use these unmanaged functions from within the managed .NET environment, we need
        to explicitly import the functions which we will be using from other .DLL file(s).  Simply
        including the appropriate header files is not enough. 

        Note: In order to avoid potential name conflicts in the header files (which we still use),
        I have renamed the functions by adding "UM" (unmanaged) onto the end of them.  To find 
        documentation for the functions in MSDN, search for the function name without the extra 
        "UM" attached.
        Note2: In the header files (such as setupapi.h), normally the function names are 
        remapped, depending upon if UNICODE is defined or not.  For example, two versions of the
        function SetupDiGetDeviceInterfaceDetail() exist.  One for UNICODE, and one for ANSI.  
        If the wrong version of the function is called, things won't work correctly.  Therefore,
        in order to make sure the correct one gets called (based on your compiler settings, which
        may or may not define "UNICODE"), it is useful to explicity specify the CharSet when doing
        the DLL import.
        */

        #ifdef UNICODE
        #define Seeifdef        Unicode
        #else
        #define Seeifdef        Ansi
        #endif


        //使用するDLL関数の宣言
        //Returns a HDEVINFO type for a device information set (USB HID devices in
        //our case).  We will need the HDEVINFO as in input parameter for calling many of
        //the other SetupDixxx() functions.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetClassDevs", CallingConvention=CallingConvention::Winapi)]                
        extern "C" HDEVINFO  SetupDiGetClassDevsUM(
                LPGUID  ClassGuid,                                      //Input: Supply the class GUID here. 
                PCTSTR  Enumerator,                                     //Input: Use NULL here, not important for our purposes
                HWND  hwndParent,                                       //Input: Use NULL here, not important for our purposes
                DWORD  Flags);                                          //Input: Flags describing what kind of filtering to use.

        //Gives us "PSP_DEVICE_INTERFACE_DATA" which contains the Interface specific GUID (different
        //from class GUID).  We need the interface GUID to get the device path.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInterfaces", CallingConvention=CallingConvention::Winapi)]                                
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInterfacesUM(
                HDEVINFO  DeviceInfoSet,                        //Input: Give it the HDEVINFO we got from SetupDiGetClassDevs()
                PSP_DEVINFO_DATA  DeviceInfoData,       //Input (optional)
                LPGUID  InterfaceClassGuid,                     //Input 
                DWORD  MemberIndex,                                     //Input: "Index" of the device you are interested in getting the path for.
                PSP_DEVICE_INTERFACE_DATA  DeviceInterfaceData);//Output: This function fills in an "SP_DEVICE_INTERFACE_DATA" structure.

        //SetupDiDestroyDeviceInfoList() frees up memory by destroying a DeviceInfoList
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiDestroyDeviceInfoList", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiDestroyDeviceInfoListUM(                     
                HDEVINFO  DeviceInfoSet);                       //Input: Give it a handle to a device info list to deallocate from RAM.

        //SetupDiEnumDeviceInfo() fills in an "SP_DEVINFO_DATA" structure, which we need for SetupDiGetDeviceRegistryProperty()
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInfo", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInfoUM(
                HDEVINFO  DeviceInfoSet,
                DWORD  MemberIndex,
                PSP_DEVINFO_DATA  DeviceInfoData);

        //SetupDiGetDeviceRegistryProperty() gives us the hardware ID, which we use to check to see if it has matching VID/PID
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceRegistryProperty", CallingConvention=CallingConvention::Winapi)]
        extern "C"      WINSETUPAPI BOOL WINAPI  SetupDiGetDeviceRegistryPropertyUM(
                HDEVINFO  DeviceInfoSet,
                PSP_DEVINFO_DATA  DeviceInfoData,
                DWORD  Property,
                PDWORD  PropertyRegDataType,
                PBYTE  PropertyBuffer,   
                DWORD  PropertyBufferSize,  
                PDWORD  RequiredSize);

        //SetupDiGetDeviceInterfaceDetail() gives us a device path, which is needed before CreateFile() can be used.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceInterfaceDetail", CallingConvention=CallingConvention::Winapi)]
        extern "C" BOOL SetupDiGetDeviceInterfaceDetailUM(
                HDEVINFO DeviceInfoSet,                                                                         //Input: Wants HDEVINFO which can be obtained from SetupDiGetClassDevs()
                PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,                          //Input: Pointer to an structure which defines the device interface.  
                PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,     //Output: Pointer to a strucutre, which will contain the device path.
                DWORD DeviceInterfaceDetailDataSize,                                            //Input: Number of bytes to retrieve.
                PDWORD RequiredSize,                                                                            //Output (optional): Te number of bytes needed to hold the entire struct 
                PSP_DEVINFO_DATA DeviceInfoData);                                                       //Output


//  Variables that need to have wide scope.
        HANDLE WriteHandle = INVALID_HANDLE_VALUE;      //Need to get a write "handle" to our device before we can write to it.
        HANDLE ReadHandle = INVALID_HANDLE_VALUE;       //Need to get a read "handle" to our device before we can read from it.
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------

        //グローバル変数定義 
        int Led0Mode = 0,       // LedMode = 0; 消灯 1:点灯
                Led1Mode = 0,   // Led1Mode = 0; 消灯 1:点灯
                Led2Mode = 0,   // Led2Mode = 0; 消灯 1:点灯
                Led3Mode = 0;   // Lee3Mode = 0; 消灯 1:点灯        

        
        DWORD BytesWritten = 0;
        DWORD BytesRead = 0;
        unsigned char OutputPacketBuffer[65];   //Allocate a memory buffer equal to our endpoint size + 1
        unsigned char InputPacketBuffer[65];



        /// <summary>
        /// Form1 の概要
        /// </summary>
        public ref class Form1 : public System::Windows::Forms::Form
        {
        public:
                Form1(void)
                {
                        InitializeComponent();
                        //
                        //TODO: ここにコンストラクター コードを追加します
                        //
                }

        protected:
                /// <summary>
                /// 使用中のリソースをすべてクリーンアップします。
                /// </summary>
                ~Form1()
                {
                        if (components)
                        {
                                delete components;
                        }
                }
        private: System::Windows::Forms::GroupBox^  groupBox1;
        private: System::Windows::Forms::Button^  Led0Btn;
        protected: 

        private: System::Windows::Forms::Button^  ConnectBtn;
        private: System::Windows::Forms::TextBox^  textBox1;
        private: System::Windows::Forms::Button^  Led1Btn;
        private: System::Windows::Forms::Button^  Led2Btn;
        private: System::Windows::Forms::Button^  Led3Btn;
        private: System::Windows::Forms::GroupBox^  groupBox2;
        private: System::Windows::Forms::Label^  label3;
        private: System::Windows::Forms::Label^  label2;
        private: System::Windows::Forms::Label^  label1;
        private: Microsoft::VisualBasic::PowerPacks::ShapeContainer^  shapeContainer1;
        private: Microsoft::VisualBasic::PowerPacks::OvalShape^  ovalShape3;
        private: Microsoft::VisualBasic::PowerPacks::OvalShape^  ovalShape2;
        private: Microsoft::VisualBasic::PowerPacks::OvalShape^  ovalShape1;
        private: System::Windows::Forms::Timer^  timer1;
        private: System::Windows::Forms::GroupBox^  groupBox3;
        private: System::Windows::Forms::TextBox^  textBox2;
        private: System::ComponentModel::IContainer^  components;

        private:
                /// <summary>
                /// 必要なデザイナー変数です。
                /// </summary>


#pragma region Windows Form Designer generated code
                /// <summary>
                /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
                /// コード エディターで変更しないでください。
                /// </summary>
                void InitializeComponent(void)
                {
                        this->components = (gcnew System::ComponentModel::Container());
                        this->groupBox1 = (gcnew System::Windows::Forms::GroupBox());
                        this->Led3Btn = (gcnew System::Windows::Forms::Button());
                        this->Led2Btn = (gcnew System::Windows::Forms::Button());
                        this->Led1Btn = (gcnew System::Windows::Forms::Button());
                        this->Led0Btn = (gcnew System::Windows::Forms::Button());
                        this->ConnectBtn = (gcnew System::Windows::Forms::Button());
                        this->textBox1 = (gcnew System::Windows::Forms::TextBox());
                        this->groupBox2 = (gcnew System::Windows::Forms::GroupBox());
                        this->label3 = (gcnew System::Windows::Forms::Label());
                        this->label2 = (gcnew System::Windows::Forms::Label());
                        this->label1 = (gcnew System::Windows::Forms::Label());
                        this->shapeContainer1 = (gcnew Microsoft::VisualBasic::PowerPacks::ShapeContainer());
                        this->ovalShape3 = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape());
                        this->ovalShape2 = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape());
                        this->ovalShape1 = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape());
                        this->timer1 = (gcnew System::Windows::Forms::Timer(this->components));
                        this->groupBox3 = (gcnew System::Windows::Forms::GroupBox());
                        this->textBox2 = (gcnew System::Windows::Forms::TextBox());
                        this->groupBox1->SuspendLayout();
                        this->groupBox2->SuspendLayout();
                        this->groupBox3->SuspendLayout();
                        this->SuspendLayout();
                        // 
                        // groupBox1
                        // 
                        this->groupBox1->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(0)), static_cast<System::Int32>(static_cast<System::Byte>(192)), 
                                static_cast<System::Int32>(static_cast<System::Byte>(192)));
                        this->groupBox1->Controls->Add(this->Led3Btn);
                        this->groupBox1->Controls->Add(this->Led2Btn);
                        this->groupBox1->Controls->Add(this->Led1Btn);
                        this->groupBox1->Controls->Add(this->Led0Btn);
                        this->groupBox1->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 10.2F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
                                static_cast<System::Byte>(128)));
                        this->groupBox1->Location = System::Drawing::Point(24, 63);
                        this->groupBox1->Name = L"groupBox1";
                        this->groupBox1->Size = System::Drawing::Size(501, 122);
                        this->groupBox1->TabIndex = 0;
                        this->groupBox1->TabStop = false;
                        this->groupBox1->Text = L"LED OnOff照光スイッチ";
                        // 
                        // Led3Btn
                        // 
                        this->Led3Btn->Location = System::Drawing::Point(347, 44);
                        this->Led3Btn->Name = L"Led3Btn";
                        this->Led3Btn->Size = System::Drawing::Size(105, 57);
                        this->Led3Btn->TabIndex = 3;
                        this->Led3Btn->Text = L"LED3";
                        this->Led3Btn->UseVisualStyleBackColor = true;
                        this->Led3Btn->Click += gcnew System::EventHandler(this, &Form1::Led3Btn_Click);
                        // 
                        // Led2Btn
                        // 
                        this->Led2Btn->Location = System::Drawing::Point(236, 44);
                        this->Led2Btn->Name = L"Led2Btn";
                        this->Led2Btn->Size = System::Drawing::Size(105, 57);
                        this->Led2Btn->TabIndex = 2;
                        this->Led2Btn->Text = L"LED2";
                        this->Led2Btn->UseVisualStyleBackColor = true;
                        this->Led2Btn->Click += gcnew System::EventHandler(this, &Form1::Led2Btn_Click);
                        // 
                        // Led1Btn
                        // 
                        this->Led1Btn->Location = System::Drawing::Point(125, 44);
                        this->Led1Btn->Name = L"Led1Btn";
                        this->Led1Btn->Size = System::Drawing::Size(105, 57);
                        this->Led1Btn->TabIndex = 1;
                        this->Led1Btn->Text = L"LED1";
                        this->Led1Btn->UseVisualStyleBackColor = true;
                        this->Led1Btn->Click += gcnew System::EventHandler(this, &Form1::Led1Btn_Click);
                        // 
                        // Led0Btn
                        // 
                        this->Led0Btn->Location = System::Drawing::Point(15, 44);
                        this->Led0Btn->Name = L"Led0Btn";
                        this->Led0Btn->Size = System::Drawing::Size(104, 57);
                        this->Led0Btn->TabIndex = 0;
                        this->Led0Btn->Text = L"LED0";
                        this->Led0Btn->UseVisualStyleBackColor = true;
                        this->Led0Btn->Click += gcnew System::EventHandler(this, &Form1::Led0Btn_Click);
                        // 
                        // ConnectBtn
                        // 
                        this->ConnectBtn->Location = System::Drawing::Point(24, 12);
                        this->ConnectBtn->Name = L"ConnectBtn";
                        this->ConnectBtn->Size = System::Drawing::Size(75, 33);
                        this->ConnectBtn->TabIndex = 1;
                        this->ConnectBtn->Text = L"接続";
                        this->ConnectBtn->UseVisualStyleBackColor = true;
                        this->ConnectBtn->Click += gcnew System::EventHandler(this, &Form1::ConnectBtn_Click);
                        // 
                        // textBox1
                        // 
                        this->textBox1->Location = System::Drawing::Point(149, 18);
                        this->textBox1->Name = L"textBox1";
                        this->textBox1->Size = System::Drawing::Size(161, 22);
                        this->textBox1->TabIndex = 2;
                        // 
                        // groupBox2
                        // 
                        this->groupBox2->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(0)), static_cast<System::Int32>(static_cast<System::Byte>(192)), 
                                static_cast<System::Int32>(static_cast<System::Byte>(192)));
                        this->groupBox2->Controls->Add(this->label3);
                        this->groupBox2->Controls->Add(this->label2);
                        this->groupBox2->Controls->Add(this->label1);
                        this->groupBox2->Controls->Add(this->shapeContainer1);
                        this->groupBox2->Location = System::Drawing::Point(24, 204);
                        this->groupBox2->Name = L"groupBox2";
                        this->groupBox2->Size = System::Drawing::Size(446, 114);
                        this->groupBox2->TabIndex = 3;
                        this->groupBox2->TabStop = false;
                        this->groupBox2->Text = L"スイッチ状態検出";
                        // 
                        // label3
                        // 
                        this->label3->AutoSize = true;
                        this->label3->Location = System::Drawing::Point(307, 90);
                        this->label3->Name = L"label3";
                        this->label3->Size = System::Drawing::Size(72, 15);
                        this->label3->TabIndex = 3;
                        this->label3->Text = L"SW3(RD7)";
                        // 
                        // label2
                        // 
                        this->label2->AutoSize = true;
                        this->label2->Location = System::Drawing::Point(189, 90);
                        this->label2->Name = L"label2";
                        this->label2->Size = System::Drawing::Size(72, 15);
                        this->label2->TabIndex = 2;
                        this->label2->Text = L"SW2(RD6)";
                        // 
                        // label1
                        // 
                        this->label1->AutoSize = true;
                        this->label1->Location = System::Drawing::Point(83, 90);
                        this->label1->Name = L"label1";
                        this->label1->Size = System::Drawing::Size(80, 15);
                        this->label1->TabIndex = 1;
                        this->label1->Text = L"SW1(RD13)";
                        // 
                        // shapeContainer1
                        // 
                        this->shapeContainer1->Location = System::Drawing::Point(3, 18);
                        this->shapeContainer1->Margin = System::Windows::Forms::Padding(0);
                        this->shapeContainer1->Name = L"shapeContainer1";
                        this->shapeContainer1->Shapes->AddRange(gcnew cli::array< Microsoft::VisualBasic::PowerPacks::Shape^  >(3) {this->ovalShape3, 
                                this->ovalShape2, this->ovalShape1});
                        this->shapeContainer1->Size = System::Drawing::Size(440, 93);
                        this->shapeContainer1->TabIndex = 0;
                        this->shapeContainer1->TabStop = false;
                        // 
                        // ovalShape3
                        // 
                        this->ovalShape3->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid;
                        this->ovalShape3->Location = System::Drawing::Point(307, 7);
                        this->ovalShape3->Name = L"ovalShape3";
                        this->ovalShape3->Size = System::Drawing::Size(50, 50);
                        // 
                        // ovalShape2
                        // 
                        this->ovalShape2->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid;
                        this->ovalShape2->Location = System::Drawing::Point(193, 10);
                        this->ovalShape2->Name = L"ovalShape2";
                        this->ovalShape2->Size = System::Drawing::Size(50, 50);
                        // 
                        // ovalShape1
                        // 
                        this->ovalShape1->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid;
                        this->ovalShape1->Location = System::Drawing::Point(81, 10);
                        this->ovalShape1->Name = L"ovalShape1";
                        this->ovalShape1->Size = System::Drawing::Size(50, 50);
                        // 
                        // timer1
                        // 
                        this->timer1->Tick += gcnew System::EventHandler(this, &Form1::timer1_Tick);
                        // 
                        // groupBox3
                        // 
                        this->groupBox3->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(0)), static_cast<System::Int32>(static_cast<System::Byte>(192)), 
                                static_cast<System::Int32>(static_cast<System::Byte>(192)));
                        this->groupBox3->Controls->Add(this->textBox2);
                        this->groupBox3->Location = System::Drawing::Point(137, 345);
                        this->groupBox3->Name = L"groupBox3";
                        this->groupBox3->Size = System::Drawing::Size(228, 71);
                        this->groupBox3->TabIndex = 4;
                        this->groupBox3->TabStop = false;
                        this->groupBox3->Text = L"電圧検出";
                        // 
                        // textBox2
                        // 
                        this->textBox2->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 13.8F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
                                static_cast<System::Byte>(128)));
                        this->textBox2->Location = System::Drawing::Point(60, 21);
                        this->textBox2->Name = L"textBox2";
                        this->textBox2->Size = System::Drawing::Size(129, 30);
                        this->textBox2->TabIndex = 0;
                        // 
                        // Form1
                        // 
                        this->AutoScaleDimensions = System::Drawing::SizeF(8, 15);
                        this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
                        this->ClientSize = System::Drawing::Size(537, 466);
                        this->Controls->Add(this->groupBox3);
                        this->Controls->Add(this->groupBox2);
                        this->Controls->Add(this->textBox1);
                        this->Controls->Add(this->ConnectBtn);
                        this->Controls->Add(this->groupBox1);
                        this->Name = L"Form1";
                        this->Text = L"Form1";
                        this->groupBox1->ResumeLayout(false);
                        this->groupBox2->ResumeLayout(false);
                        this->groupBox2->PerformLayout();
                        this->groupBox3->ResumeLayout(false);
                        this->groupBox3->PerformLayout();
                        this->ResumeLayout(false);
                        this->PerformLayout();

                }
#pragma endregion
        private: System::Void ConnectBtn_Click(System::Object^  sender, System::EventArgs^  e) 
                         {
                                 
                                 //-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
                /* 
                Before we can "connect" our application to our USB embedded device, we must first find the device.
                A USB bus can have many devices simultaneously connected, so somehow we have to find our device, and only
                our device.  This is done with the Vendor ID (VID) and Product ID (PID).  Each USB product line should have
                a unique combination of VID and PID.  

                Microsoft has created a number of functions which are useful for finding plug and play devices.  Documentation
                for each function used can be found in the MSDN library.  We will be using the following functions:

                SetupDiGetClassDevs()                                   //provided by setupapi.dll, which comes with Windows
                SetupDiEnumDeviceInterfaces()                   //provided by setupapi.dll, which comes with Windows
                GetLastError()                                                  //provided by kernel32.dll, which comes with Windows
                SetupDiDestroyDeviceInfoList()                  //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceInterfaceDetail()               //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceRegistryProperty()              //provided by setupapi.dll, which comes with Windows
                malloc()                                                                //part of C runtime library, msvcrt.dll?
                CreateFile()                                                    //provided by kernel32.dll, which comes with Windows

                We will also be using the following unusual data types and structures.  Documentation can also be found in
                the MSDN library:

                PSP_DEVICE_INTERFACE_DATA
                PSP_DEVICE_INTERFACE_DETAIL_DATA
                SP_DEVINFO_DATA
                HDEVINFO
                HANDLE
                GUID

                The ultimate objective of the following code is to call CreateFile(), which opens a communications
                pipe to a specific device (such as a HID class USB device endpoint).  CreateFile() returns a "handle" 
                which is needed later when calling ReadFile() or WriteFile().  These functions are used to actually 
                send and receive application related data to/from the USB peripheral device.

                However, in order to call CreateFile(), we first need to get the device path for the USB device
                with the correct VID and PID.  Getting the device path is a multi-step round about process, which
                requires calling several of the SetupDixxx() functions provided by setupapi.dll.
                */


                //Globally Unique Identifier (GUID) for HID class devices.  Windows uses GUIDs to identify things.
                GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}; 

                HDEVINFO DeviceInfoTable = INVALID_HANDLE_VALUE;
                PSP_DEVICE_INTERFACE_DATA InterfaceDataStructure = new SP_DEVICE_INTERFACE_DATA;
                PSP_DEVICE_INTERFACE_DETAIL_DATA DetailedInterfaceDataStructure = new SP_DEVICE_INTERFACE_DETAIL_DATA;
                SP_DEVINFO_DATA DevInfoData;

                DWORD InterfaceIndex = 0;
                DWORD StatusLastError = 0;
                DWORD dwRegType;
                DWORD dwRegSize;
                DWORD StructureSize = 0;
                PBYTE PropertyValueBuffer;
                bool MatchFound = false;
                DWORD ErrorStatus;

                String^ DeviceIDToFind = MY_DEVICE_ID;

                //First populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID. 
                DeviceInfoTable = SetupDiGetClassDevsUM(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

                //Now look through the list we just populated.  We are trying to see if any of them match our device. 
                while(true)
                {
                        InterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
                        if(SetupDiEnumDeviceInterfacesUM(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, InterfaceDataStructure))
                        {
                                ErrorStatus = GetLastError();
                                if(ERROR_NO_MORE_ITEMS == ErrorStatus)  //Did we reach the end of the list of matching devices in the DeviceInfoTable?
                                {       //Cound not find the device.  Must not have been attached.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                        }
                        else    //Else some other kind of unknown error ocurred...
                        {
                                ErrorStatus = GetLastError();
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return; 
                        }

                        //Now retrieve the hardware ID from the registry.  The hardware ID contains the VID and PID, which we will then 
                        //check to see if it is the correct device or not.

                        //Initialize an appropriate SP_DEVINFO_DATA structure.  We need this structure for SetupDiGetDeviceRegistryProperty().
                        DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
                        SetupDiEnumDeviceInfoUM(DeviceInfoTable, InterfaceIndex, &DevInfoData);

                        //First query for the size of the hardware ID, so we can know how big a buffer to allocate for the data.
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, NULL, 0, &dwRegSize);

                        //Allocate a buffer for the hardware ID.
                        PropertyValueBuffer = (BYTE *) malloc (dwRegSize);
                        if(PropertyValueBuffer == NULL) //if null, error, couldn't allocate enough memory
                        {       //Can't really recover from this situation, just exit instead.
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return;         
                        }

                        //Retrieve the hardware IDs for the current device we are looking at.  PropertyValueBuffer gets filled with a 
                        //REG_MULTI_SZ (array of null terminated strings).  To find a device, we only care about the very first string in the
                        //buffer, which will be the "device ID".  The device ID is a string which contains the VID and PID, in the example 
                        //format "Vid_04d8&Pid_003f".
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, PropertyValueBuffer, dwRegSize, NULL);

                        //Now check if the first string in the hardware ID matches the device ID of my USB device.
                        #ifdef UNICODE
                        String^ DeviceIDFromRegistry = gcnew String((wchar_t *)PropertyValueBuffer);
                        #else
                        String^ DeviceIDFromRegistry = gcnew String((char *)PropertyValueBuffer);
                        #endif

                        free(PropertyValueBuffer);              //No longer need the PropertyValueBuffer, free the memory to prevent potential memory leaks
                        textBox1->Text = "Searching Device!";
                        //Convert both strings to lower case.  This makes the code more robust/portable accross OS Versions
                        DeviceIDFromRegistry = DeviceIDFromRegistry->ToLowerInvariant();        
                        DeviceIDToFind = DeviceIDToFind->ToLowerInvariant();                            
                        //Now check if the hardware ID we are looking at contains the correct VID/PID
                        MatchFound = DeviceIDFromRegistry->Contains(DeviceIDToFind);            
                        if(MatchFound == true)
                        {
                                //Device must have been found.  Open read and write handles.  In order to do this, we will need the actual device path first.
                                //We can get the path by calling SetupDiGetDeviceInterfaceDetail(), however, we have to call this function twice:  The first
                                //time to get the size of the required structure/buffer to hold the detailed interface data, then a second time to actually 
                                //get the structure (after we have allocated enough memory for the structure.)
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                //First call populates "StructureSize" with the correct value
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL);   
                                DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize));             //Allocate enough memory
                                if(DetailedInterfaceDataStructure == NULL)      //if null, error, couldn't allocate enough memory
                                {       //Can't really recover from this situation, just exit instead.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                 //Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods.  
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); 

                                //We now have the proper device path, and we can finally open read and write handles to the device.
                                //We store the handles in the global variables "WriteHandle" and "ReadHandle", which we will use later to actually communicate.
                                WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);

                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                        textBox1->Text = "Write Enabled.";                              //Make button no longer greyed out
                                ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                {
                                        textBox1->Text = "Read Enabled.";                                       //Make label no longer greyed out
                                }
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.


                                //追加修正部
                                // 接続確認メッセージ準備 
                                OutputPacketBuffer[0] = 0;                                                      // Report ID  
                                OutputPacketBuffer[1] = 0x30;                                           // 接続確認 
                                // 接続確認 コマンド送信
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                // OK受信
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                                // OK確認 
                                if((InputPacketBuffer[3] == 0x4F)&&(InputPacketBuffer[4] == 0x4B))      //"OK"  //O: 0x4F //K: 0x4B
                                        textBox1->Text = "接続完了!!";                              // 接続正常完了

                                

                                // 接続完了でタイマ1スタート
                                timer1->Interval = 100;
                                timer1->Enabled = TRUE;


                                return;
                        }

                        InterfaceIndex++;       
                        //Keep looping until we either find a device with matching VID and PID, or until we run out of items.
                }//end of while(true)   
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------

                         }
        private: System::Void Led0Btn_Click(System::Object^  sender, System::EventArgs^  e)
                         {
                                OutputPacketBuffer[0] = 0;                                      // Report ID  
                                OutputPacketBuffer[1] = 0x80;                           // LED制御コマンド

                                OutputPacketBuffer[2] = 0x30;                           // LED0アドレス

                                if(Led0Mode == 0)       //消灯していたなら
                                {
                                        Led0Mode = 1;
                                        OutputPacketBuffer[3] = 0x31;                   // Led点灯        //0x31 = '1'
                                }
                                else
                                {
                                        Led0Mode = 0;
                                        OutputPacketBuffer[3] = 0x30;                   // Led消灯        //0x30 = '0'
                                }

                                // 送信
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                // 受信
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                                if(InputPacketBuffer[3] == 0x31)Led0Btn->BackColor =Color:: Red;                // オンなら赤
                                else Led0Btn->BackColor = Color::Gray;          // オフなら灰色

                         }
private: System::Void Led1Btn_Click(System::Object^  sender, System::EventArgs^  e) 
                 {
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x80;                           // LED制御コマンド

                        OutputPacketBuffer[2] = 0x31;                           // LED1アドレス

                        if(Led1Mode == 0)       //消灯していたなら
                        {
                                Led1Mode = 1;
                                OutputPacketBuffer[3] = 0x31;                   // Led点灯        //0x31 = '1'
                        }
                        else
                        {
                                Led1Mode = 0;
                                OutputPacketBuffer[3] = 0x30;                   // Led消灯        //0x30 = '0'
                        }

                        // 送信
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                        // 受信
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                        if(InputPacketBuffer[4] == 0x31)Led1Btn->BackColor =Color:: Red;                // オンなら赤
                        else Led1Btn->BackColor = Color::Gray;          // オフなら灰色
                 }
private: System::Void Led2Btn_Click(System::Object^  sender, System::EventArgs^  e)
                 {
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x80;                           // LED制御コマンド

                        OutputPacketBuffer[2] = 0x32;                           // LED1アドレス

                        if(Led2Mode == 0)       //消灯していたなら
                        {
                                Led2Mode = 1;
                                OutputPacketBuffer[3] = 0x31;                   // Led点灯        //0x31 = '1'
                        }
                        else
                        {
                                Led2Mode = 0;
                                OutputPacketBuffer[3] = 0x30;                   // Led消灯        //0x30 = '0'
                        }

                        // 送信
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                        // 受信
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                        if(InputPacketBuffer[5] == 0x31)Led2Btn->BackColor =Color:: Red;                // オンなら赤
                        else Led2Btn->BackColor = Color::Gray;          // オフなら灰色



                 }
private: System::Void Led3Btn_Click(System::Object^  sender, System::EventArgs^  e)
                 {
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x80;                           // LED制御コマンド

                        OutputPacketBuffer[2] = 0x33;                           // LED1アドレス

                        if(Led3Mode == 0)       //消灯していたなら
                        {
                                Led3Mode = 1;
                                OutputPacketBuffer[3] = 0x31;                   // Led点灯        //0x31 = '1'
                        }
                        else
                        {
                                Led3Mode = 0;
                                OutputPacketBuffer[3] = 0x30;                   // Led消灯        //0x30 = '0'
                        }

                        // 送信
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                        // 受信
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                        if(InputPacketBuffer[6] == 0x31)Led3Btn->BackColor =Color:: Red;                // オンなら赤
                        else Led3Btn->BackColor = Color::Gray;          // オフなら灰色



                 }
private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e)
                 {
                         unsigned int ADCValue;
                                double Volt;

                        //可変抵抗器出力電圧のAD変換値 読込
                
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x82;                           // 可変抵抗器outのAD変換値読込

                        OutputPacketBuffer[2] = 0x31;                           // VR1
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);

                        //対応するエンドポイント
                        //InputPacketBuffer[3](Windows側)vs ToSendDataBuffer[2](PIC側)
                        //InputPacketBuffer[4](Windows側)vs ToSendDataBuffer[3](PIC側)
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                        ADCValue = (InputPacketBuffer[4] * 256) + InputPacketBuffer[3];
                        Volt = (ADCValue * 5.0) / 1024;
                        textBox2->Text = String::Format("{0:F2} [V]",Volt);             //小数点以下2桁にして表示



                         //スイッチの状態読込
                                
                                OutputPacketBuffer[0] = 0;                                      // Report ID  
                                OutputPacketBuffer[1] = 0x81;                           // SW状態要求コマンド

                                OutputPacketBuffer[2] = 0x31;                           // SW1
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                //ovalShape: FillStyleのpropertyはSolidに設定のこと//コマンドでは設定できない!!
                                if(InputPacketBuffer[3] == 0x30)                        // オンか? 
                                        ovalShape1->FillColor = Color::Orange;  //ON ならオレンジ色
                                else
                                        ovalShape1->FillColor = Color::Gray;            // OFFなら灰色

                                //ovalShape: FillStyleのpropertyはSolidに設定のこと//コマンドでは設定できない!!
                                OutputPacketBuffer[2] = 0x32;                           // SW2
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                if(InputPacketBuffer[3] == 0x30)                        // オンか? 
                                        ovalShape2->FillColor = Color::Orange;  //ON ならオレンジ色
                                else
                                        ovalShape2->FillColor = Color::Gray;            // OFFなら灰色

                                //ovalShape: FillStyleのpropertyはSolidに設定のこと//コマンドでは設定できない!!
                                OutputPacketBuffer[2] = 0x33;                           // SW3
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                if(InputPacketBuffer[3] == 0x30)                        // オンか? 
                                        ovalShape3->FillColor = Color::Orange;  //ON ならオレンジ色
                                else
                                        ovalShape3->FillColor = Color::Gray;            // OFFなら灰色
                 }
};
}

}
 

<実行結果>

 PC画面のLED0,LED2、LED3ボタンをクリックして キバン上のLEDを点灯させたあと、キバン上のSW1とSW3をおした時のPCのスクリーンショット画像とキバンの写真です。
ADコンバータで検出された電圧が ダイアログのテキストボックスに小数点以下2桁で3.53[V}と表示されています。

パソコン画面の
  ダイアログ
PIC32MX795F512L キバン上で
  SW1 とSW3を押したところ




■ PIC32MX795F512L  HIDクラス 漢字を含む文字列の送受信

  PIC32MX795F512Lにキャラクタ液晶を接続した USB通信 送受信の例を紹介します。   → PIC側ハード&ソフト

以下のソフトは、 マイクロチップ社のライブラリ microchip_solutions_v2013-06-15\USB\Simple Demo - Windows Software \Microsoft Visual C++ 2005 Expressに収納されているVC++Cのサンプルプログラムを参考にして作成したものです。


<試作品仕様>
 ・PC側からデータをPIC側にUSB HIDクラス通信で送信する。
 ・送信文字コードはシフトJISを使用する
 ・PIC側では受信した文字列を液晶上段に、受信データに基づき返信したデータを液晶下段に表示する。
 ・PC側でも受信したデータをリストボックスに表示する。
 ・PC側からの送信データ 及びPIC側からの返信データは以下とする。
     @ U.K.       →  London
     A America    →  Washington
     B Japan      →  0x938c(東)0x8b9e(京)
     C 中(0x9286)国 (0x8D91)   → 北(0x966B)京(0x8B9E)
     D I am a boy.   →  Pardon ?


  

          

   <プログラム例>


//Form1.h


#pragma once
//Includes
#include <Windows.h>    //Definitions for various common and not so common types like DWORD, PCHAR, HANDLE, etc.
#include <setupapi.h>   //From Platform SDK. Definitions needed for the SetupDixxx() functions, which we use to
                                                //find our plug and play device.
#include <Winusb.h>             // WINUSB_INTERFACE_HANDLE(インターフェース用ハンドル)が定義されている       

#include <msclr/marshal.h>      //マーシャリング関係関数用

//Modify this value to match the VID and PID in your USB device descriptor.
//Use the formatting: "Vid_xxxx&Pid_xxxx" where xxxx is a 16-bit hexadecimal number.
#define MY_DEVICE_ID  "Vid_04d8&Pid_003F"               //VID = 0x04D8  PID = 0x003F    




namespace CWhiteForm {

        using namespace System;
        using namespace System::ComponentModel;
        using namespace System::Collections;
        using namespace System::Windows::Forms;
        using namespace System::Data;
        using namespace System::Drawing;

        using namespace System::Text;//エンコードクラスを使用する場合要追加
        using namespace msclr::interop; //マーシャリング関係関数用

        //-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
        using namespace System::Runtime::InteropServices;  //Need this to support "unmanaged" code.

        /*
        In order to use these unmanaged functions from within the managed .NET environment, we need
        to explicitly import the functions which we will be using from other .DLL file(s).  Simply
        including the appropriate header files is not enough. 

        Note: In order to avoid potential name conflicts in the header files (which we still use),
        I have renamed the functions by adding "UM" (unmanaged) onto the end of them.  To find 
        documentation for the functions in MSDN, search for the function name without the extra 
        "UM" attached.
        Note2: In the header files (such as setupapi.h), normally the function names are 
        remapped, depending upon if UNICODE is defined or not.  For example, two versions of the
        function SetupDiGetDeviceInterfaceDetail() exist.  One for UNICODE, and one for ANSI.  
        If the wrong version of the function is called, things won't work correctly.  Therefore,
        in order to make sure the correct one gets called (based on your compiler settings, which
        may or may not define "UNICODE"), it is useful to explicity specify the CharSet when doing
        the DLL import.
        */

        #ifdef UNICODE
        #define Seeifdef        Unicode
        #else
        #define Seeifdef        Ansi
        #endif


        //使用するDLL関数の宣言
        //Returns a HDEVINFO type for a device information set (USB HID devices in
        //our case).  We will need the HDEVINFO as in input parameter for calling many of
        //the other SetupDixxx() functions.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetClassDevs", CallingConvention=CallingConvention::Winapi)]                
        extern "C" HDEVINFO  SetupDiGetClassDevsUM(
                LPGUID  ClassGuid,                                      //Input: Supply the class GUID here. 
                PCTSTR  Enumerator,                                     //Input: Use NULL here, not important for our purposes
                HWND  hwndParent,                                       //Input: Use NULL here, not important for our purposes
                DWORD  Flags);                                          //Input: Flags describing what kind of filtering to use.

        //Gives us "PSP_DEVICE_INTERFACE_DATA" which contains the Interface specific GUID (different
        //from class GUID).  We need the interface GUID to get the device path.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInterfaces", CallingConvention=CallingConvention::Winapi)]                                
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInterfacesUM(
                HDEVINFO  DeviceInfoSet,                        //Input: Give it the HDEVINFO we got from SetupDiGetClassDevs()
                PSP_DEVINFO_DATA  DeviceInfoData,       //Input (optional)
                LPGUID  InterfaceClassGuid,                     //Input 
                DWORD  MemberIndex,                                     //Input: "Index" of the device you are interested in getting the path for.
                PSP_DEVICE_INTERFACE_DATA  DeviceInterfaceData);//Output: This function fills in an "SP_DEVICE_INTERFACE_DATA" structure.

        //SetupDiDestroyDeviceInfoList() frees up memory by destroying a DeviceInfoList
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiDestroyDeviceInfoList", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiDestroyDeviceInfoListUM(                     
                HDEVINFO  DeviceInfoSet);                       //Input: Give it a handle to a device info list to deallocate from RAM.

        //SetupDiEnumDeviceInfo() fills in an "SP_DEVINFO_DATA" structure, which we need for SetupDiGetDeviceRegistryProperty()
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInfo", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInfoUM(
                HDEVINFO  DeviceInfoSet,
                DWORD  MemberIndex,
                PSP_DEVINFO_DATA  DeviceInfoData);

        //SetupDiGetDeviceRegistryProperty() gives us the hardware ID, which we use to check to see if it has matching VID/PID
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceRegistryProperty", CallingConvention=CallingConvention::Winapi)]
        extern "C"      WINSETUPAPI BOOL WINAPI  SetupDiGetDeviceRegistryPropertyUM(
                HDEVINFO  DeviceInfoSet,
                PSP_DEVINFO_DATA  DeviceInfoData,
                DWORD  Property,
                PDWORD  PropertyRegDataType,
                PBYTE  PropertyBuffer,   
                DWORD  PropertyBufferSize,  
                PDWORD  RequiredSize);

        //SetupDiGetDeviceInterfaceDetail() gives us a device path, which is needed before CreateFile() can be used.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceInterfaceDetail", CallingConvention=CallingConvention::Winapi)]
        extern "C" BOOL SetupDiGetDeviceInterfaceDetailUM(
                HDEVINFO DeviceInfoSet,                                                                         //Input: Wants HDEVINFO which can be obtained from SetupDiGetClassDevs()
                PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,                          //Input: Pointer to an structure which defines the device interface.  
                PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,     //Output: Pointer to a strucutre, which will contain the device path.
                DWORD DeviceInterfaceDetailDataSize,                                            //Input: Number of bytes to retrieve.
                PDWORD RequiredSize,                                                                            //Output (optional): Te number of bytes needed to hold the entire struct 
                PSP_DEVINFO_DATA DeviceInfoData);                                                       //Output

        //USBデバイスとのパイプ(エンドポイント)に書き込む関数
        //WinUsb_WritePipe() is the basic function used to write data to the USB device (sends data to OUT endpoints on the device)
        [DllImport("winusb.dll" , CharSet = CharSet::Seeifdef, EntryPoint="WinUsb_WritePipe")]
        extern "C" BOOL WinUsb_WritePipe(
                WINUSB_INTERFACE_HANDLE InterfaceHandle,
                UCHAR PipeID,
                PUCHAR Buffer,
                ULONG BufferLength,
                PULONG LengthTransferred,
                LPOVERLAPPED Overlapped);

        //USBデバイスとのパイプ(エンドポイント)からデータを読み込む関数
        //WinUsb_ReadPipe() is the basic function used to read data from the USB device (polls for and obtains data from
        //IN endpoints on the device)
        [DllImport("winusb.dll" , CharSet = CharSet::Seeifdef, EntryPoint="WinUsb_ReadPipe")]
        extern "C" BOOL WinUsb_ReadPipe(
                WINUSB_INTERFACE_HANDLE InterfaceHandle,        //The interface handle that WinUsb_Initialize returned. 
                UCHAR PipeID,   //An 8-bit value that consists of a 7-bit address and a direction bit.
                                                //This parameter corresponds to the bEndpointAddress field in the endpoint descriptor. 

                PUCHAR Buffer,  //A caller-allocated buffer that receives the data that is read. 

                ULONG BufferLength,     //The maximum number of bytes to read. This number must be less than or equal to the size, in bytes, of Buffer. 

                PULONG LengthTransferred,       //A pointer to a ULONG variable that receives the actual number of bytes that were copied into Buffer. 

                LPOVERLAPPED Overlapped);       //An optional pointer to an OVERLAPPED structure that is used for asynchronous operations. If this
                                                                        //parameter is specified, WinUsb_ReadPipe returns immediately rather than waiting synchronously 
                                                                        //for the operation to complete before returning. An event is signaled when the operation is complete. 



//  Variables that need to have wide scope.
        HANDLE WriteHandle = INVALID_HANDLE_VALUE;      //Need to get a write "handle" to our device before we can write to it.
        HANDLE ReadHandle = INVALID_HANDLE_VALUE;       //Need to get a read "handle" to our device before we can read from it.
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------

        
        //グローバル変数定義

        
        DWORD BytesWritten = 0;         //書き込んだバイト数
        DWORD BytesRead = 0;            //読み込んだバイト数
        unsigned char OutputPacketBuffer[65];   //Allocate a memory buffer equal to our endpoint size + 1
        unsigned char InputPacketBuffer[65];

        
//グローバル変数
        HANDLE MyDeviceHandle = INVALID_HANDLE_VALUE;           //USBデバイス用のハンドル
        WINUSB_INTERFACE_HANDLE MyWinUSBInterfaceHandle;        //インターフェース用ハンドル
                                                                                                                //And then can call WinUsb_Initialize() to get the interface handle
                                                                                                                //which is needed for doing other operations with the device (like
                                                                                                                //reading and writing to the USB device).




        /// <summary>
        /// Form1 の概要
        /// </summary>
        public ref class Form1 : public System::Windows::Forms::Form
        {
        public:
                Form1(void)
                {
                        InitializeComponent();
                        comboBox1->Items->Clear();
                        comboBox1->Items->Insert(0,"U.K.              ");
                        comboBox1->Items->Insert(1,"America           ");
                        comboBox1->Items->Insert(2,"Japan             ");
                        comboBox1->Items->Insert(3,"中国              ");
                        //comboBox1->Items->Insert(3,"Chuugoku          ");
                        comboBox1->Items->Insert(4,"I am a boy.           ");
                        comboBox1->SelectedIndex = 0; 

                        SendBtn->Enabled = false;       //送信ボタンをディスイネーブル化

                        textBox1->Text = "未接続";
                        textBox1->ForeColor = Color::Red;
                }

        protected:
                /// <summary>
                /// 使用中のリソースをすべてクリーンアップします。
                /// </summary>
                ~Form1()
                {
                        if (components)
                        {
                                delete components;
                        }
                }



#pragma endregion
        private: System::Void ConnectBtn_Click(System::Object^  sender, System::EventArgs^  e) 
                         {


                                 
                                 
                                 //-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
                /*
                Before we can "connect" our application to our USB embedded device, we must first find the device.
                A USB bus can have many devices simultaneously connected, so somehow we have to find our device, and only
                our device.  This is done with the Vendor ID (VID) and Product ID (PID).  Each USB product line should have
                a unique combination of VID and PID.  

                Microsoft has created a number of functions which are useful for finding plug and play devices.  Documentation
                for each function used can be found in the MSDN library.  We will be using the following functions:

                SetupDiGetClassDevs()                                   //provided by setupapi.dll, which comes with Windows
                SetupDiEnumDeviceInterfaces()                   //provided by setupapi.dll, which comes with Windows
                GetLastError()                                                  //provided by kernel32.dll, which comes with Windows
                SetupDiDestroyDeviceInfoList()                  //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceInterfaceDetail()               //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceRegistryProperty()              //provided by setupapi.dll, which comes with Windows
                malloc()                                                                //part of C runtime library, msvcrt.dll?
                CreateFile()                                                    //provided by kernel32.dll, which comes with Windows

                We will also be using the following unusual data types and structures.  Documentation can also be found in
                the MSDN library:

                PSP_DEVICE_INTERFACE_DATA
                PSP_DEVICE_INTERFACE_DETAIL_DATA
                SP_DEVINFO_DATA
                HDEVINFO
                HANDLE
                GUID

                The ultimate objective of the following code is to call CreateFile(), which opens a communications
                pipe to a specific device (such as a HID class USB device endpoint).  CreateFile() returns a "handle" 
                which is needed later when calling ReadFile() or WriteFile().  These functions are used to actually 
                send and receive application related data to/from the USB peripheral device.

                However, in order to call CreateFile(), we first need to get the device path for the USB device
                with the correct VID and PID.  Getting the device path is a multi-step round about process, which
                requires calling several of the SetupDixxx() functions provided by setupapi.dll.
                */






                //Globally Unique Identifier (GUID) for HID class devices.  Windows uses GUIDs to identify things.
                GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}; 

                HDEVINFO DeviceInfoTable = INVALID_HANDLE_VALUE;
                PSP_DEVICE_INTERFACE_DATA InterfaceDataStructure = new SP_DEVICE_INTERFACE_DATA;
                PSP_DEVICE_INTERFACE_DETAIL_DATA DetailedInterfaceDataStructure = new SP_DEVICE_INTERFACE_DETAIL_DATA;
                SP_DEVINFO_DATA DevInfoData;

                DWORD InterfaceIndex = 0;
                DWORD StatusLastError = 0;
                DWORD dwRegType;
                DWORD dwRegSize;
                DWORD StructureSize = 0;
                PBYTE PropertyValueBuffer;
                bool MatchFound = false;
                DWORD ErrorStatus;

                String^ DeviceIDToFind = MY_DEVICE_ID;

                //First populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID. 
                DeviceInfoTable = SetupDiGetClassDevsUM(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

                //Now look through the list we just populated.  We are trying to see if any of them match our device. 
                while(true)
                {
                        InterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
                        if(SetupDiEnumDeviceInterfacesUM(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, InterfaceDataStructure))
                        {
                                ErrorStatus = GetLastError();
                                if(ERROR_NO_MORE_ITEMS == ErrorStatus)  //Did we reach the end of the list of matching devices in the DeviceInfoTable?
                                {       //Cound not find the device.  Must not have been attached.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                        }
                        else    //Else some other kind of unknown error ocurred...
                        {
                                ErrorStatus = GetLastError();
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return; 
                        }

                        //Now retrieve the hardware ID from the registry.  The hardware ID contains the VID and PID, which we will then 
                        //check to see if it is the correct device or not.

                        //Initialize an appropriate SP_DEVINFO_DATA structure.  We need this structure for SetupDiGetDeviceRegistryProperty().
                        DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
                        SetupDiEnumDeviceInfoUM(DeviceInfoTable, InterfaceIndex, &DevInfoData);

                        //First query for the size of the hardware ID, so we can know how big a buffer to allocate for the data.
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, NULL, 0, &dwRegSize);

                        //Allocate a buffer for the hardware ID.
                        PropertyValueBuffer = (BYTE *) malloc (dwRegSize);
                        if(PropertyValueBuffer == NULL) //if null, error, couldn't allocate enough memory
                        {       //Can't really recover from this situation, just exit instead.
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return;         
                        }

                        //Retrieve the hardware IDs for the current device we are looking at.  PropertyValueBuffer gets filled with a 
                        //REG_MULTI_SZ (array of null terminated strings).  To find a device, we only care about the very first string in the
                        //buffer, which will be the "device ID".  The device ID is a string which contains the VID and PID, in the example 
                        //format "Vid_04d8&Pid_003f".
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, PropertyValueBuffer, dwRegSize, NULL);

                        //Now check if the first string in the hardware ID matches the device ID of my USB device.
                        #ifdef UNICODE
                        String^ DeviceIDFromRegistry = gcnew String((wchar_t *)PropertyValueBuffer);
                        #else
                        String^ DeviceIDFromRegistry = gcnew String((char *)PropertyValueBuffer);
                        #endif

                        free(PropertyValueBuffer);              //No longer need the PropertyValueBuffer, free the memory to prevent potential memory leaks
                        textBox1->Text = "Searching Device!";
                        //Convert both strings to lower case.  This makes the code more robust/portable accross OS Versions
                        DeviceIDFromRegistry = DeviceIDFromRegistry->ToLowerInvariant();        
                        DeviceIDToFind = DeviceIDToFind->ToLowerInvariant();                            
                        //Now check if the hardware ID we are looking at contains the correct VID/PID
                        MatchFound = DeviceIDFromRegistry->Contains(DeviceIDToFind);            
                        if(MatchFound == true)
                        {
                                //Device must have been found.  Open read and write handles.  In order to do this, we will need the actual device path first.
                                //We can get the path by calling SetupDiGetDeviceInterfaceDetail(), however, we have to call this function twice:  The first
                                //time to get the size of the required structure/buffer to hold the detailed interface data, then a second time to actually 
                                //get the structure (after we have allocated enough memory for the structure.)
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                //First call populates "StructureSize" with the correct value
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL);   
                                DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize));             //Allocate enough memory
                                if(DetailedInterfaceDataStructure == NULL)      //if null, error, couldn't allocate enough memory
                                {       //Can't really recover from this situation, just exit instead.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                 //Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods.  
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); 

                                //We now have the proper device path, and we can finally open read and write handles to the device.
                                //We store the handles in the global variables "WriteHandle" and "ReadHandle", which we will use later to actually communicate.
                                WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);

                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                        textBox1->Text = "Write Enabled.";                              //Make button no longer greyed out
                                ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                {
                                        textBox1->Text = "Read Enabled.";                                       //Make label no longer greyed out
                                }
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.


                                //追加修正部
                                // 接続確認メッセージ準備 
                                OutputPacketBuffer[0] = 0;                                                      // Report ID  
                                OutputPacketBuffer[1] = 0x30;                                           // 接続確認 
                                // 接続確認 コマンド送信
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                // OK受信
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                                // OK確認 
                                if((InputPacketBuffer[3] == 0x4F)&&(InputPacketBuffer[4] == 0x4B))      //"OK"  //O: 0x4F //K: 0x4B
                                        textBox1->Text = "接続完了!!";                              // 接続正常完了
                                        textBox1->ForeColor = Color::Blue;                      //文字色→青色

                                        listBox1->Items->Clear();
                                        SendBtn->Enabled = true;        //送信ボタン→イネーブル


                                return;
                        }

                        InterfaceIndex++;       
                        //Keep looping until we either find a device with matching VID and PID, or until we run out of items.
                }//end of while(true)   
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------

                         }
private: System::Void SendBtn_Click(System::Object^  sender, System::EventArgs^  e)
                 {

                         
                        int i;
                        int iy;

                        array <Byte>^ bytesArry = gcnew array<Byte>(65);        //マネージ形式の配列の宣言
                        Encoding^ encSjis = Encoding::GetEncoding("shift-jis");   //シフトJISのエンコードクラスを宣言 & インスタンス生成
                        Encoding^ encUni = Encoding::GetEncoding("unicode");  //ユニコード(UCS-16)のエンコードクラスを宣言 & インスタンス生成


                        String^ strSend = comboBox1->Text;

                        richTextBox1-> Clear();
                        richTextBox2-> Clear();
                        richTextBox3-> Clear();

                        if (!strSend->EndsWith("\r")) strSend += "\r";  //改行が無かったら \rを追加する
                        bytesArry = encSjis->GetBytes( strSend ); //'送信文字をunicode→Shift-jisに変換してをByte配列に格納

                        for(i = 2; i < bytesArry->Length - 1 ; i++)OutputPacketBuffer[i] = bytesArry[i - 2];            //マネージ形式の配列をC言語の配列に変換

                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x80;                           // 制御コマンド


                        //リッチテキスト
                                 array<String^>^ mBX = gcnew array<String^>(65);        //アスキー文字のメモリ    //マネージ配列を定義
                                 array<String^>^ mBX16 = gcnew array<String^>(65);      //16進数のメモリ      //マネージ配列を定義


                                                                          iy = 0;
                                 for each(char s in OutputPacketBuffer) //charの配列BX[64]すべてに対して実行
                                 {
                                         char ch = (char)OutputPacketBuffer[iy];
                                         char* ptr;
                                         ptr = &ch;
                                         mBX[iy] = marshal_as<String^>(ptr);             //配列の値をマーシャリング
                                         int Ix = (int)OutputPacketBuffer[iy];
                                         mBX16[iy] = Convert::ToString(Ix,16); //整数を16進表示の文字列に変換する

                                         richTextBox1->SelectedText =                   //リッチテキストに表示
                                         String::Format("OutBuf[{0}]:     {1},       {2}       0x{3}\r",iy,mBX[iy],Ix,mBX16[iy]);

                                         iy++;

                                 }




                        // 送信
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                        //       受信
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        

                        
                        for(i = 0; i < 17;  i++)
                        {
                                        bytesArry[i] = InputPacketBuffer[i + 1];                //マネージ型配列作成
                        }

                

                                richTextBox2->SelectedText = String::Format("InputBuffer[0]={0:X} ",InputPacketBuffer[0]); //リッチテキストに表示
                                richTextBox2->SelectedText = String::Format("InputBuffer[1]={0:X} ",InputPacketBuffer[1]);
                                richTextBox2->SelectedText = String::Format("InputBuffer[2]={0:X} ",InputPacketBuffer[2]); 
                                richTextBox2->SelectedText = String::Format("InputBuffer[3]={0:X} ",InputPacketBuffer[3]);
                                richTextBox2->SelectedText = String::Format("InputBuffer[4]={0:X} ",InputPacketBuffer[4]); 
                                richTextBox2->SelectedText = String::Format("InputBuffer[5]={0:X} ",InputPacketBuffer[5]);
                                richTextBox2->SelectedText = String::Format("InputBuffer[6]={0:X} ",InputPacketBuffer[6]); 
                                richTextBox2->SelectedText = String::Format("InputBuffer[7]={0:X} ",InputPacketBuffer[7]);
                                richTextBox2->SelectedText = String::Format("InputBuffer[8]={0:X} ",InputPacketBuffer[8]); 
                                richTextBox2->SelectedText = String::Format("InputBuffer[9]={0:X} ",InputPacketBuffer[9]);



                

                                richTextBox3->SelectedText = String::Format("bytesArry[0]={0:X} ",bytesArry[0]);        //リッチテキストに表示
                                richTextBox3->SelectedText = String::Format("bytesArry[1]={0:X} ",bytesArry[1]);
                                richTextBox3->SelectedText = String::Format("bytesArry[2]={0:X} ",bytesArry[2]);
                                richTextBox3->SelectedText = String::Format("bytesArry[3]={0:X} ",bytesArry[3]);
                                richTextBox3->SelectedText = String::Format("bytesArry[4]={0:X} ",bytesArry[4]);
                                richTextBox3->SelectedText = String::Format("bytesArry[5]={0:X} ",bytesArry[5]);
                                richTextBox3->SelectedText = String::Format("bytesArry[6]={0:X} ",bytesArry[6]);
                                richTextBox3->SelectedText = String::Format("bytesArry[7]={0:X} ",bytesArry[7]);
                                richTextBox3->SelectedText = String::Format("bytesArry[8]={0:X} ",bytesArry[8]);
                                richTextBox3->SelectedText = String::Format("bytesArry[9]={0:X} ",bytesArry[9]);




                        
                        array<Byte>^byteUni = Encoding::Convert(encSjis, encUni, bytesArry); //shift-jis からunicodeに変換する
          
                        
                        String^ strUni = encUni->GetString(byteUni); //配列をunicodeの文字列に変換

                        
                        listBox1->Items->Add(strUni);
                 }
};
}

.......
.......



<実行結果>
 
PIC32MX795F512Lの液晶
上段: PCからの受信文字列
下段: PCへの返信文字列
PC画面
USB接続が
    未接続の状態
-
接続ボタンをクリックして
  USB接続が
    確立した状態
-
コンボボックスから
”U.K.”を選択して送信し、
返信をリストボックスに
     受信した状態
次に、コンボボックスから
”America”を選択して送信し、
返信をリストボックスに
     受信した状態
次に、コンボボックスから
”Japan”を選択して送信し、
返信をリストボックスに
     受信した状態
次に、コンボボックスから
”中国”を選択して送信し、
返信をリストボックスに
     受信した状態
最後に、コンボボックスから
”I am a boy”を選択して送信し、
返信をリストボックスに
     受信した状態

■ PIC32MZ2048EFH100
      HIDクラス IO制御(LED/点灯消灯、ADコンバータ・スイッチ読込・表示
                    (サンプルプログラム(VC++プロジェクトファイル) → ダウンロード
                      (サンプルプログラム(実行ファイル) → ダウンロード

                                   ★ PIC側のハードとソフトは こちらを参照願います


<仕様>
  ・PCとPIC間のUSB通信はHIDクラスとする。
  ・PICはPIC32MZ2048EFH100を使用のこと。
  ・PC側のプログラムは、マイクロソフトのVC++で作成のこと。
  ・PC側はダイアログウィンドウを作成して、以下を実施できること。
     @ PIC側のLEDのON/OFF制御
     A PIC側のスイッチの状態のモニタ
     B PIC側の可変抵抗器の電圧もモニタ
  ・ダイアログウィンドウのボタンスイッチ(コントロール)のクリックにより、PIC側のLEDがON/OFFできること。
  ・ボタンスイッチの背景色はLEDがONの場合は赤色、LEDがOFFの場合は灰色とする。
  ・ボタンコントロールはLEDがONの場合は赤色に、OFFの場合は灰色とする。
  ・LEDがONの場合は画像を またOFFの場合は画像を表示のこと。
  ・PIC側のスイッチのON/OFF状態が分かるモニターとして 円形のオーバルシェープコントロールを使用のこと。
   尚、色はONの場合はオレンジ色、OFFの場合は灰色とする。
  ・スイッチがONの場合は画像を またOFFの場合は画像を表示のこと。画像は重ねて配置のこと。
  ・PIC側の可変抵抗器の電圧値に表示のこと。値は四捨五入して小数点以下2桁を表示のこと。
  ・入力電圧値がビジュアルにわかるようにプログレスバーでも表示のこと。
  ・途中切断も含め、USB通信がOFFの場合はLED,、スイッチ、可変抵抗器などに係る表示は行わないようにすること。
  ・PCのアプリケーションは100msec毎にPIC側の状態をサンプリングのこと。
  ・ PC側のダイアログウィンドウ例を以下に示す。      

    
   <USB通信OFFの場合>  <USB通信がONの場合>


    ・PIC側のモニタ用液晶として、I2C制御のキャラクタ液晶を用いること。
    ・PICが起動する時、キャラクタ液晶には以下を表示のこと。 
      1行目: USB device HID
      2行目: start !!
    ・USB通信が始まったら液晶に可変抵抗器の入力電圧をモニタする。
      1行目: AdValue= ◯◯◯◯   
      2行目: Volt= ◯◯◯◯[V]
     AdValueの〇〇〇〇は内臓ADコンバータの読み込み整数値、Voltは電圧換算値で小数点以下3桁を表示のこと。
    ・可変抵抗器の電圧のサンプリングタイムは50msecとする。
    ・USBケーブルが送受信中に抜かれたりして通信が切断された場合は LED、スイッチ、可変抵抗器のPictureBoxはDisableとなり ダイアログウィンドウ画面は 上記の <USB通信OFFの場合>の画面に戻ること。
   

          

以下、プログラム抜粋

//Form1.h デザイン

          

   

//Form1.h #pragma once //以下は、マイクロチップのサンプルコード //"C:\microchip_solutions_v2013-06-15\USB\Device - HID - Custom Demos\Simple Demo - Windows Software\Microsoft Visual C++ 2005 Express" //を参照して作成しています。 //------------------------------------------------------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------BEGIN CUT AND PASTE BLOCK----------------------------------------------------------------------------------- /******************************************************************** FileName: Form1.h Dependencies: Platform SDK during development. When compiled, needs .NET framework 2.0 redistributable to run Processor: x86 Hardware: Need a free USB port to connect USB peripheral device Compiler: Microsoft Visual C++ 2005 Express Edition (or better) Company: Microchip Technology, Inc. Software License Agreement: The software supplied herewith by Microchip Technology Incorporated (the 鼎ompany・ for its PICョ Microcontroller is intended and supplied to you, the Company痴 customer, for use solely and exclusively with Microchip PIC Microcontroller products. The software is owned by the Company and/or its supplier, and is protected under applicable copyright laws. All rights are reserved. Any use in violation of the foregoing restrictions may subject the user to criminal sanctions under applicable laws, as well as to civil liability for the breach of the terms and conditions of this license. THIS SOFTWARE IS PROVIDED IN AN 鄭S IS・CONDITION. NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. ******************************************************************** File Description: Change History: Rev Date Description 1.0 04/08/2008 Initial release 2.3 08/11/2008 Slight update for improved robustness 2.7a 08/29/2010 Adding explicit calling conventions to the DllImports. This is needed for Visual Studio 2010 compatibility. No functional changes to the code. Backwards compatibility should be retained. ******************************************************************** NOTE: All user made code contained in this project is in the Form1.h file. All other code and files were generated automatically by either the new project wizard, or by the development environment (ex: code is automatically generated if you create a new button on the form, and then double click on it, which creates a click event handler function). All user made code is contained in clearly marked cut and paste blocks. ********************************************************************/ //Includes //Includes #include <Windows.h> //Definitions for various common and not so common types like DWORD, PCHAR, HANDLE, etc. #include <setupapi.h> //From Platform SDK. Definitions needed for the SetupDixxx() functions, which we use to //find our plug and play device. //Modify this value to match the VID and PID in your USB device descriptor. //Use the formatting: "Vid_xxxx&Pid_xxxx" where xxxx is a 16-bit hexadecimal number. #define MY_DEVICE_ID "Vid_04d8&Pid_003F" //-------------------------------------------------------END CUT AND PASTE BLOCK------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------------------------------------------------------- //本プロジェクトの名前空間に変更 namespace CWhiteForm { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; // //namespace GenericHIDSimpleDemo { // // using namespace System; // using namespace System::ComponentModel; // using namespace System::Collections; // using namespace System::Windows::Forms; // using namespace System::Data; // using namespace System::Drawing; //------------------------------------------------------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------BEGIN CUT AND PASTE BLOCK----------------------------------------------------------------------------------- using namespace System::Runtime::InteropServices; //Need this to support "unmanaged" code. /* In order to use these unmanaged functions from within the managed .NET environment, we need to explicitly import the functions which we will be using from other .DLL file(s). Simply including the appropriate header files is not enough. Note: In order to avoid potential name conflicts in the header files (which we still use), I have renamed the functions by adding "UM" (unmanaged) onto the end of them. To find documentation for the functions in MSDN, search for the function name without the extra "UM" attached. Note2: In the header files (such as setupapi.h), normally the function names are remapped, depending upon if UNICODE is defined or not. For example, two versions of the function SetupDiGetDeviceInterfaceDetail() exist. One for UNICODE, and one for ANSI. If the wrong version of the function is called, things won't work correctly. Therefore, in order to make sure the correct one gets called (based on your compiler settings, which may or may not define "UNICODE"), it is useful to explicity specify the CharSet when doing the DLL import. */ #ifdef UNICODE #define Seeifdef Unicode #else #define Seeifdef Ansi #endif //Returns a HDEVINFO type for a device information set (USB HID devices in //our case). We will need the HDEVINFO as in input parameter for calling many of //the other SetupDixxx() functions. [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetClassDevs", CallingConvention=CallingConvention::Winapi)] extern "C" HDEVINFO SetupDiGetClassDevsUM( LPGUID ClassGuid, //Input: Supply the class GUID here. PCTSTR Enumerator, //Input: Use NULL here, not important for our purposes HWND hwndParent, //Input: Use NULL here, not important for our purposes DWORD Flags); //Input: Flags describing what kind of filtering to use. //Gives us "PSP_DEVICE_INTERFACE_DATA" which contains the Interface specific GUID (different //from class GUID). We need the interface GUID to get the device path. [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInterfaces", CallingConvention=CallingConvention::Winapi)] extern "C" WINSETUPAPI BOOL WINAPI SetupDiEnumDeviceInterfacesUM( HDEVINFO DeviceInfoSet, //Input: Give it the HDEVINFO we got from SetupDiGetClassDevs() PSP_DEVINFO_DATA DeviceInfoData, //Input (optional) LPGUID InterfaceClassGuid, //Input DWORD MemberIndex, //Input: "Index" of the device you are interested in getting the path for. PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData);//Output: This function fills in an "SP_DEVICE_INTERFACE_DATA" structure. //SetupDiDestroyDeviceInfoList() frees up memory by destroying a DeviceInfoList [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiDestroyDeviceInfoList", CallingConvention=CallingConvention::Winapi)] extern "C" WINSETUPAPI BOOL WINAPI SetupDiDestroyDeviceInfoListUM( HDEVINFO DeviceInfoSet); //Input: Give it a handle to a device info list to deallocate from RAM. //SetupDiEnumDeviceInfo() fills in an "SP_DEVINFO_DATA" structure, which we need for SetupDiGetDeviceRegistryProperty() [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInfo", CallingConvention=CallingConvention::Winapi)] extern "C" WINSETUPAPI BOOL WINAPI SetupDiEnumDeviceInfoUM( HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData); //SetupDiGetDeviceRegistryProperty() gives us the hardware ID, which we use to check to see if it has matching VID/PID [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceRegistryProperty", CallingConvention=CallingConvention::Winapi)] extern "C" WINSETUPAPI BOOL WINAPI SetupDiGetDeviceRegistryPropertyUM( HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize); //SetupDiGetDeviceInterfaceDetail() gives us a device path, which is needed before CreateFile() can be used. [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceInterfaceDetail", CallingConvention=CallingConvention::Winapi)] extern "C" BOOL SetupDiGetDeviceInterfaceDetailUM( HDEVINFO DeviceInfoSet, //Input: Wants HDEVINFO which can be obtained from SetupDiGetClassDevs() PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, //Input: Pointer to an structure which defines the device interface. PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, //Output: Pointer to a strucutre, which will contain the device path. DWORD DeviceInterfaceDetailDataSize, //Input: Number of bytes to retrieve. PDWORD RequiredSize, //Output (optional): Te number of bytes needed to hold the entire struct PSP_DEVINFO_DATA DeviceInfoData); //Output // Variables that need to have wide scope. HANDLE WriteHandle = INVALID_HANDLE_VALUE; //Need to get a write "handle" to our device before we can write to it. HANDLE ReadHandle = INVALID_HANDLE_VALUE; //Need to get a read "handle" to our device before we can read from it. //-------------------------------------------------------END CUT AND PASTE BLOCK------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------------------------------------------------------- //グローバル変数定義 int LedMode = 0; // LedMode = 0; 消灯 1:点灯 int ConnectFlag = 0; DWORD BytesWritten = 0; DWORD BytesRead = 0; unsigned char OutputPacketBuffer[65]; //Allocate a memory buffer equal to our endpoint size + 1 unsigned char InputPacketBuffer[65]; /// <summary> /// Form1 の概要 /// </summary> public ref class Form1 : public System::Windows::Forms::Form { public: Form1(void) { InitializeComponent(); // //TODO: ここにコンストラクター コードを追加します // groupBox1->Visible = false; groupBox2->Visible = false; groupBox3->Visible = false; OnLed_pictureBox->Visible = false; //Led オン画像非表示 OffLed_pictureBox->Visible = true; //Led オフ画像表示 OnSw_pictureBox->Visible = false; //SW オン画像非表示 OffSw_pictureBox->Visible = true; //SW オフ画像表示 VR_progressBar->Value = 0; } protected: /// <summary> /// 使用中のリソースをすべてクリーンアップします。 /// </summary> ~Form1() { if (components) { delete components; } } private: System::Windows::Forms::Label^ label1; protected: private: System::Windows::Forms::Button^ USB_ConnectBtn; private: Microsoft::VisualBasic::PowerPacks::ShapeContainer^ shapeContainer1; private: Microsoft::VisualBasic::PowerPacks::OvalShape^ ovalShape1; private: System::Windows::Forms::Label^ ConnectLabel; private: System::Windows::Forms::Timer^ timer1; private: System::Windows::Forms::GroupBox^ groupBox1; private: System::Windows::Forms::GroupBox^ groupBox2; private: System::Windows::Forms::GroupBox^ groupBox3; private: System::Windows::Forms::PictureBox^ OffLed_pictureBox; private: System::Windows::Forms::Button^ LedBtn; private: Microsoft::VisualBasic::PowerPacks::ShapeContainer^ shapeContainer2; private: Microsoft::VisualBasic::PowerPacks::OvalShape^ SwLamp_ovalShape; private: System::Windows::Forms::PictureBox^ OnLed_pictureBox; private: System::Windows::Forms::PictureBox^ OffSw_pictureBox; private: System::Windows::Forms::PictureBox^ OnSw_pictureBox; private: System::Windows::Forms::ProgressBar^ VR_progressBar; private: System::Windows::Forms::Label^ label3; private: System::Windows::Forms::Label^ label2; private: System::Windows::Forms::TextBox^ VR_textBox; private: System::Windows::Forms::Label^ label5; private: System::Windows::Forms::Label^ label4; private: System::ComponentModel::IContainer^ components; protected: protected: private: /// <summary> /// 必要なデザイナー変数です。 /// </summary> #pragma region Windows Form Designer generated code /// <summary> /// デザイナー サポートに必要なメソッドです。このメソッドの内容を /// コード エディターで変更しないでください。 /// </summary> void InitializeComponent(void) { this->components = (gcnew System::ComponentModel::Container()); System::ComponentModel::ComponentResourceManager^ resources = (gcnew System::ComponentModel::ComponentResourceManager(Form1::typeid)); this->label1 = (gcnew System::Windows::Forms::Label()); this->USB_ConnectBtn = (gcnew System::Windows::Forms::Button()); this->shapeContainer1 = (gcnew Microsoft::VisualBasic::PowerPacks::ShapeContainer()); this->ovalShape1 = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape()); this->ConnectLabel = (gcnew System::Windows::Forms::Label()); this->timer1 = (gcnew System::Windows::Forms::Timer(this->components)); this->groupBox1 = (gcnew System::Windows::Forms::GroupBox()); this->OffLed_pictureBox = (gcnew System::Windows::Forms::PictureBox()); this->OnLed_pictureBox = (gcnew System::Windows::Forms::PictureBox()); this->LedBtn = (gcnew System::Windows::Forms::Button()); this->groupBox2 = (gcnew System::Windows::Forms::GroupBox()); this->OffSw_pictureBox = (gcnew System::Windows::Forms::PictureBox()); this->OnSw_pictureBox = (gcnew System::Windows::Forms::PictureBox()); this->shapeContainer2 = (gcnew Microsoft::VisualBasic::PowerPacks::ShapeContainer()); this->SwLamp_ovalShape = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape()); this->groupBox3 = (gcnew System::Windows::Forms::GroupBox()); this->label5 = (gcnew System::Windows::Forms::Label()); this->label4 = (gcnew System::Windows::Forms::Label()); this->VR_progressBar = (gcnew System::Windows::Forms::ProgressBar()); this->label3 = (gcnew System::Windows::Forms::Label()); this->label2 = (gcnew System::Windows::Forms::Label()); this->VR_textBox = (gcnew System::Windows::Forms::TextBox()); this->groupBox1->SuspendLayout(); (cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->OffLed_pictureBox))->BeginInit(); (cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->OnLed_pictureBox))->BeginInit(); this->groupBox2->SuspendLayout(); (cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->OffSw_pictureBox))->BeginInit(); (cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->OnSw_pictureBox))->BeginInit(); this->groupBox3->SuspendLayout(); this->SuspendLayout(); // // label1 // this->label1->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(128))); this->label1->Location = System::Drawing::Point(12, 29); this->label1->Name = L"label1"; this->label1->Size = System::Drawing::Size(100, 50); this->label1->TabIndex = 0; this->label1->Text = L"USB 接続"; this->label1->TextAlign = System::Drawing::ContentAlignment::MiddleCenter; // // USB_ConnectBtn // this->USB_ConnectBtn->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(128))); this->USB_ConnectBtn->Location = System::Drawing::Point(118, 38); this->USB_ConnectBtn->Name = L"USB_ConnectBtn"; this->USB_ConnectBtn->Size = System::Drawing::Size(104, 33); this->USB_ConnectBtn->TabIndex = 1; this->USB_ConnectBtn->Text = L"接続"; this->USB_ConnectBtn->UseVisualStyleBackColor = true; this->USB_ConnectBtn->Click += gcnew System::EventHandler(this, &Form1::USB_ConnectBtn_Click); // // shapeContainer1 // this->shapeContainer1->Location = System::Drawing::Point(0, 0); this->shapeContainer1->Margin = System::Windows::Forms::Padding(0); this->shapeContainer1->Name = L"shapeContainer1"; this->shapeContainer1->Shapes->AddRange(gcnew cli::array< Microsoft::VisualBasic::PowerPacks::Shape^ >(1) {this->ovalShape1}); this->shapeContainer1->Size = System::Drawing::Size(372, 513); this->shapeContainer1->TabIndex = 2; this->shapeContainer1->TabStop = false; // // ovalShape1 // this->ovalShape1->FillColor = System::Drawing::Color::Gray; this->ovalShape1->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid; this->ovalShape1->Location = System::Drawing::Point(281, 13); this->ovalShape1->Name = L"ovalShape1"; this->ovalShape1->Size = System::Drawing::Size(50, 50); this->ovalShape1->Click += gcnew System::EventHandler(this, &Form1::ovalShape1_Click); // // ConnectLabel // this->ConnectLabel->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(128))); this->ConnectLabel->Location = System::Drawing::Point(247, 66); this->ConnectLabel->Name = L"ConnectLabel"; this->ConnectLabel->Size = System::Drawing::Size(100, 23); this->ConnectLabel->TabIndex = 3; this->ConnectLabel->Text = L"未接続"; this->ConnectLabel->TextAlign = System::Drawing::ContentAlignment::BottomRight; // // timer1 // this->timer1->Tick += gcnew System::EventHandler(this, &Form1::timer1_Tick); // // groupBox1 // this->groupBox1->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(128)), static_cast<System::Int32>(static_cast<System::Byte>(255)), static_cast<System::Int32>(static_cast<System::Byte>(128))); this->groupBox1->Controls->Add(this->OffLed_pictureBox); this->groupBox1->Controls->Add(this->OnLed_pictureBox); this->groupBox1->Controls->Add(this->LedBtn); this->groupBox1->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(128))); this->groupBox1->Location = System::Drawing::Point(22, 92); this->groupBox1->Name = L"groupBox1"; this->groupBox1->Size = System::Drawing::Size(325, 139); this->groupBox1->TabIndex = 4; this->groupBox1->TabStop = false; this->groupBox1->Text = L"LED"; this->groupBox1->Enter += gcnew System::EventHandler(this, &Form1::groupBox1_Enter); // // OffLed_pictureBox // this->OffLed_pictureBox->Image = (cli::safe_cast<System::Drawing::Image^ >(resources->GetObject(L"OffLed_pictureBox.Image"))); this->OffLed_pictureBox->Location = System::Drawing::Point(166, 29); this->OffLed_pictureBox->Name = L"OffLed_pictureBox"; this->OffLed_pictureBox->Size = System::Drawing::Size(117, 44); this->OffLed_pictureBox->TabIndex = 2; this->OffLed_pictureBox->TabStop = false; // // OnLed_pictureBox // this->OnLed_pictureBox->Image = (cli::safe_cast<System::Drawing::Image^ >(resources->GetObject(L"OnLed_pictureBox.Image"))); this->OnLed_pictureBox->Location = System::Drawing::Point(36, 30); this->OnLed_pictureBox->Name = L"OnLed_pictureBox"; this->OnLed_pictureBox->Size = System::Drawing::Size(121, 43); this->OnLed_pictureBox->TabIndex = 1; this->OnLed_pictureBox->TabStop = false; // // LedBtn // this->LedBtn->Location = System::Drawing::Point(109, 79); this->LedBtn->Name = L"LedBtn"; this->LedBtn->Size = System::Drawing::Size(91, 48); this->LedBtn->TabIndex = 0; this->LedBtn->Text = L"ON/OFF"; this->LedBtn->UseVisualStyleBackColor = true; this->LedBtn->Click += gcnew System::EventHandler(this, &Form1::LedBtn_Click); // // groupBox2 // this->groupBox2->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(128)), static_cast<System::Int32>(static_cast<System::Byte>(255)), static_cast<System::Int32>(static_cast<System::Byte>(128))); this->groupBox2->Controls->Add(this->OffSw_pictureBox); this->groupBox2->Controls->Add(this->OnSw_pictureBox); this->groupBox2->Controls->Add(this->shapeContainer2); this->groupBox2->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(128))); this->groupBox2->Location = System::Drawing::Point(25, 237); this->groupBox2->Name = L"groupBox2"; this->groupBox2->Size = System::Drawing::Size(328, 106); this->groupBox2->TabIndex = 5; this->groupBox2->TabStop = false; this->groupBox2->Text = L"スイッチ"; this->groupBox2->Enter += gcnew System::EventHandler(this, &Form1::groupBox2_Enter); // // OffSw_pictureBox // this->OffSw_pictureBox->Image = (cli::safe_cast<System::Drawing::Image^ >(resources->GetObject(L"OffSw_pictureBox.Image"))); this->OffSw_pictureBox->Location = System::Drawing::Point(160, 25); this->OffSw_pictureBox->Name = L"OffSw_pictureBox"; this->OffSw_pictureBox->Size = System::Drawing::Size(120, 60); this->OffSw_pictureBox->TabIndex = 2; this->OffSw_pictureBox->TabStop = false; // // OnSw_pictureBox // this->OnSw_pictureBox->Image = (cli::safe_cast<System::Drawing::Image^ >(resources->GetObject(L"OnSw_pictureBox.Image"))); this->OnSw_pictureBox->Location = System::Drawing::Point(160, 25); this->OnSw_pictureBox->Name = L"OnSw_pictureBox"; this->OnSw_pictureBox->Size = System::Drawing::Size(120, 60); this->OnSw_pictureBox->TabIndex = 1; this->OnSw_pictureBox->TabStop = false; this->OnSw_pictureBox->Click += gcnew System::EventHandler(this, &Form1::OnSw_pictureBox_Click); // // shapeContainer2 // this->shapeContainer2->Location = System::Drawing::Point(3, 22); this->shapeContainer2->Margin = System::Windows::Forms::Padding(0); this->shapeContainer2->Name = L"shapeContainer2"; this->shapeContainer2->Shapes->AddRange(gcnew cli::array< Microsoft::VisualBasic::PowerPacks::Shape^ >(1) {this->SwLamp_ovalShape}); this->shapeContainer2->Size = System::Drawing::Size(322, 81); this->shapeContainer2->TabIndex = 0; this->shapeContainer2->TabStop = false; // // SwLamp_ovalShape // this->SwLamp_ovalShape->FillColor = System::Drawing::Color::Gray; this->SwLamp_ovalShape->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid; this->SwLamp_ovalShape->Location = System::Drawing::Point(72, 4); this->SwLamp_ovalShape->Name = L"SwLamp_ovalShape"; this->SwLamp_ovalShape->Size = System::Drawing::Size(50, 50); // // groupBox3 // this->groupBox3->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(128)), static_cast<System::Int32>(static_cast<System::Byte>(255)), static_cast<System::Int32>(static_cast<System::Byte>(128))); this->groupBox3->Controls->Add(this->label5); this->groupBox3->Controls->Add(this->label4); this->groupBox3->Controls->Add(this->VR_progressBar); this->groupBox3->Controls->Add(this->label3); this->groupBox3->Controls->Add(this->label2); this->groupBox3->Controls->Add(this->VR_textBox); this->groupBox3->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(128))); this->groupBox3->Location = System::Drawing::Point(25, 362); this->groupBox3->Name = L"groupBox3"; this->groupBox3->Size = System::Drawing::Size(328, 139); this->groupBox3->TabIndex = 6; this->groupBox3->TabStop = false; this->groupBox3->Text = L"可変抵抗器"; // // label5 // this->label5->AutoSize = true; this->label5->Location = System::Drawing::Point(282, 72); this->label5->Name = L"label5"; this->label5->Size = System::Drawing::Size(46, 19); this->label5->TabIndex = 5; this->label5->Text = L"3.3v"; // // label4 // this->label4->AutoSize = true; this->label4->Location = System::Drawing::Point(29, 72); this->label4->Name = L"label4"; this->label4->Size = System::Drawing::Size(30, 19); this->label4->TabIndex = 4; this->label4->Text = L"0v"; this->label4->Click += gcnew System::EventHandler(this, &Form1::label4_Click); // // VR_progressBar // this->VR_progressBar->Location = System::Drawing::Point(33, 94); this->VR_progressBar->Name = L"VR_progressBar"; this->VR_progressBar->Size = System::Drawing::Size(283, 27); this->VR_progressBar->Step = 1; this->VR_progressBar->Style = System::Windows::Forms::ProgressBarStyle::Continuous; this->VR_progressBar->TabIndex = 3; // // label3 // this->label3->AutoSize = true; this->label3->Location = System::Drawing::Point(222, 41); this->label3->Name = L"label3"; this->label3->Size = System::Drawing::Size(36, 19); this->label3->TabIndex = 2; this->label3->Text = L"[V]"; // // label2 // this->label2->AutoSize = true; this->label2->Location = System::Drawing::Point(29, 41); this->label2->Name = L"label2"; this->label2->Size = System::Drawing::Size(89, 19); this->label2->TabIndex = 1; this->label2->Text = L"入力電圧"; // // VR_textBox // this->VR_textBox->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 20.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(128))); this->VR_textBox->Location = System::Drawing::Point(121, 31); this->VR_textBox->Name = L"VR_textBox"; this->VR_textBox->Size = System::Drawing::Size(95, 34); this->VR_textBox->TabIndex = 0; this->VR_textBox->TextAlign = System::Windows::Forms::HorizontalAlignment::Center; // // Form1 // this->AutoScaleDimensions = System::Drawing::SizeF(6, 12); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(372, 513); this->Controls->Add(this->groupBox3); this->Controls->Add(this->groupBox2); this->Controls->Add(this->groupBox1); this->Controls->Add(this->USB_ConnectBtn); this->Controls->Add(this->label1); this->Controls->Add(this->ConnectLabel); this->Controls->Add(this->shapeContainer1); this->Margin = System::Windows::Forms::Padding(2); this->Name = L"Form1"; this->Text = L"Form1"; this->groupBox1->ResumeLayout(false); (cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->OffLed_pictureBox))->EndInit(); (cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->OnLed_pictureBox))->EndInit(); this->groupBox2->ResumeLayout(false); (cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->OffSw_pictureBox))->EndInit(); (cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->OnSw_pictureBox))->EndInit(); this->groupBox3->ResumeLayout(false); this->groupBox3->PerformLayout(); this->ResumeLayout(false); } #pragma endregion private: System::Void USB_ConnectBtn_Click(System::Object^ sender, System::EventArgs^ e){ //------------------------------------------------------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------BEGIN CUT AND PASTE BLOCK----------------------------------------------------------------------------------- /* Before we can "connect" our application to our USB embedded device, we must first find the device. A USB bus can have many devices simultaneously connected, so somehow we have to find our device, and only our device. This is done with the Vendor ID (VID) and Product ID (PID). Each USB product line should have a unique combination of VID and PID. Microsoft has created a number of functions which are useful for finding plug and play devices. Documentation for each function used can be found in the MSDN library. We will be using the following functions: SetupDiGetClassDevs() //provided by setupapi.dll, which comes with Windows SetupDiEnumDeviceInterfaces() //provided by setupapi.dll, which comes with Windows GetLastError() //provided by kernel32.dll, which comes with Windows SetupDiDestroyDeviceInfoList() //provided by setupapi.dll, which comes with Windows SetupDiGetDeviceInterfaceDetail() //provided by setupapi.dll, which comes with Windows SetupDiGetDeviceRegistryProperty() //provided by setupapi.dll, which comes with Windows malloc() //part of C runtime library, msvcrt.dll? CreateFile() //provided by kernel32.dll, which comes with Windows We will also be using the following unusual data types and structures. Documentation can also be found in the MSDN library: PSP_DEVICE_INTERFACE_DATA PSP_DEVICE_INTERFACE_DETAIL_DATA SP_DEVINFO_DATA HDEVINFO HANDLE GUID The ultimate objective of the following code is to call CreateFile(), which opens a communications pipe to a specific device (such as a HID class USB device endpoint). CreateFile() returns a "handle" which is needed later when calling ReadFile() or WriteFile(). These functions are used to actually send and receive application related data to/from the USB peripheral device. However, in order to call CreateFile(), we first need to get the device path for the USB device with the correct VID and PID. Getting the device path is a multi-step round about process, which requires calling several of the SetupDixxx() functions provided by setupapi.dll. */ //Globally Unique Identifier (GUID) for HID class devices. Windows uses GUIDs to identify things. GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}; HDEVINFO DeviceInfoTable = INVALID_HANDLE_VALUE; PSP_DEVICE_INTERFACE_DATA InterfaceDataStructure = new SP_DEVICE_INTERFACE_DATA; PSP_DEVICE_INTERFACE_DETAIL_DATA DetailedInterfaceDataStructure = new SP_DEVICE_INTERFACE_DETAIL_DATA; SP_DEVINFO_DATA DevInfoData; DWORD InterfaceIndex = 0; DWORD StatusLastError = 0; DWORD dwRegType; DWORD dwRegSize; DWORD StructureSize = 0; PBYTE PropertyValueBuffer; bool MatchFound = false; DWORD ErrorStatus; String^ DeviceIDToFind = MY_DEVICE_ID; //First populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID. DeviceInfoTable = SetupDiGetClassDevsUM(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); //Now look through the list we just populated. We are trying to see if any of them match our device. while(true) { InterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); if(SetupDiEnumDeviceInterfacesUM(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, InterfaceDataStructure)) { ErrorStatus = GetLastError(); if(ERROR_NO_MORE_ITEMS == ErrorStatus) //Did we reach the end of the list of matching devices in the DeviceInfoTable? { //Cound not find the device. Must not have been attached. SetupDiDestroyDeviceInfoListUM(DeviceInfoTable); //Clean up the old structure we no longer need. return; } } else //Else some other kind of unknown error ocurred... { ErrorStatus = GetLastError(); SetupDiDestroyDeviceInfoListUM(DeviceInfoTable); //Clean up the old structure we no longer need. return; } //Now retrieve the hardware ID from the registry. The hardware ID contains the VID and PID, which we will then //check to see if it is the correct device or not. //Initialize an appropriate SP_DEVINFO_DATA structure. We need this structure for SetupDiGetDeviceRegistryProperty(). DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); SetupDiEnumDeviceInfoUM(DeviceInfoTable, InterfaceIndex, &DevInfoData); //First query for the size of the hardware ID, so we can know how big a buffer to allocate for the data. SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, NULL, 0, &dwRegSize); //Allocate a buffer for the hardware ID. PropertyValueBuffer = (BYTE *) malloc (dwRegSize); if(PropertyValueBuffer == NULL) //if null, error, couldn't allocate enough memory { //Can't really recover from this situation, just exit instead. SetupDiDestroyDeviceInfoListUM(DeviceInfoTable); //Clean up the old structure we no longer need. return; } //Retrieve the hardware IDs for the current device we are looking at. PropertyValueBuffer gets filled with a //REG_MULTI_SZ (array of null terminated strings). To find a device, we only care about the very first string in the //buffer, which will be the "device ID". The device ID is a string which contains the VID and PID, in the example //format "Vid_04d8&Pid_003f". SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, PropertyValueBuffer, dwRegSize, NULL); //Now check if the first string in the hardware ID matches the device ID of my USB device. #ifdef UNICODE String^ DeviceIDFromRegistry = gcnew String((wchar_t *)PropertyValueBuffer); #else String^ DeviceIDFromRegistry = gcnew String((char *)PropertyValueBuffer); #endif free(PropertyValueBuffer); //No longer need the PropertyValueBuffer, free the memory to prevent potential memory leaks //Convert both strings to lower case. This makes the code more robust/portable accross OS Versions DeviceIDFromRegistry = DeviceIDFromRegistry->ToLowerInvariant(); DeviceIDToFind = DeviceIDToFind->ToLowerInvariant(); //Now check if the hardware ID we are looking at contains the correct VID/PID MatchFound = DeviceIDFromRegistry->Contains(DeviceIDToFind); if(MatchFound == true) { //Device must have been found. Open read and write handles. In order to do this, we will need the actual device path first. //We can get the path by calling SetupDiGetDeviceInterfaceDetail(), however, we have to call this function twice: The first //time to get the size of the required structure/buffer to hold the detailed interface data, then a second time to actually //get the structure (after we have allocated enough memory for the structure.) DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); //First call populates "StructureSize" with the correct value SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL); DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize)); //Allocate enough memory if(DetailedInterfaceDataStructure == NULL) //if null, error, couldn't allocate enough memory { //Can't really recover from this situation, just exit instead. SetupDiDestroyDeviceInfoListUM(DeviceInfoTable); //Clean up the old structure we no longer need. return; } DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); //Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods. SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); //We now have the proper device path, and we can finally open read and write handles to the device. //We store the handles in the global variables "WriteHandle" and "ReadHandle", which we will use later to actually communicate. WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); ErrorStatus = GetLastError(); if(ErrorStatus == ERROR_SUCCESS) // ToggleLED_btn->Enabled = true; //Make button no longer greyed out ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); ErrorStatus = GetLastError(); if(ErrorStatus == ERROR_SUCCESS) { //USB接続 → ラベル表示、シェープ色変更 groupBox1->Visible = true; groupBox2->Visible = true; groupBox3->Visible = true; ConnectLabel->Text = "接続完了"; ovalShape1->FillColor = Color::Orange; // 接続完了ならオレンジ色 //未接続のままなら灰色 // 接続完了でタイマ1スタート timer1->Interval = 100; timer1->Enabled = TRUE; // GetPushbuttonState_btn->Enabled = true; //Make button no longer greyed out // StateLabel->Enabled = true; //Make label no longer greyed out } SetupDiDestroyDeviceInfoListUM(DeviceInfoTable); //Clean up the old structure we no longer need. return; } InterfaceIndex++; //Keep looping until we either find a device with matching VID and PID, or until we run out of items. }//end of while(true) //-------------------------------------------------------END CUT AND PASTE BLOCK------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------------------------------------------------------- } private: System::Void groupBox1_Enter(System::Object^ sender, System::EventArgs^ e) { } //LED ON/OFFボタン制御 private: System::Void LedBtn_Click(System::Object^ sender, System::EventArgs^ e) { OutputPacketBuffer[0] = 0; // Report ID OutputPacketBuffer[1] = 0x80; // LED制御コマンド OutputPacketBuffer[2] = 0x30; // LEDアドレス if(LedMode == 0) //消灯していたなら { LedMode = 1; OutputPacketBuffer[3] = 0x31; // Led点灯 //0x31 = '1' } else { LedMode = 0; OutputPacketBuffer[3] = 0x30; // Led消灯 //0x30 = '0' } // 送信 WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0); // 受信 ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0); if(InputPacketBuffer[3] == 0x31) { LedBtn->BackColor =Color:: Red; // オンなら赤 OnLed_pictureBox->Visible = true; //ONのランプ画像表示 OffLed_pictureBox->Visible = false; //OFFのランプ画像非表示 } else { LedBtn->BackColor = Color::Gray; // オフなら灰色 OnLed_pictureBox->Visible = false; //ONのランプ画像非表示 OffLed_pictureBox->Visible = true; //OFFのランプ画像表示 } } private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e) { unsigned int ADCValue; double Volt; int temp; // 接続確認確認 OutputPacketBuffer[0] = 0; // Report ID OutputPacketBuffer[1] = 0x30; // 接続確認 WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0); ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0); if(!((InputPacketBuffer[3] == 'R')&& //'R' 'e' 'a' 'd' 'y' 文字を受信できない場合 (InputPacketBuffer[4] == 'e')&& (InputPacketBuffer[5] == 'a')&& (InputPacketBuffer[6] == 'd')&& (InputPacketBuffer[7] == 'y'))) { ovalShape1->FillColor = Color::Gray; //接続表示 灰色 ConnectLabel->Text = "未接続"; groupBox1->Visible = FALSE; //グループボックス非表示 groupBox2->Visible = FALSE; groupBox3->Visible = FALSE; timer1->Enabled = FALSE; //タイマ停止 } //スイッチの状態読込 OutputPacketBuffer[0] = 0; // Report ID OutputPacketBuffer[1] = 0x81; // SW状態要求コマンド OutputPacketBuffer[2] = 0x31; // SW1 WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0); ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0); //ovalShape: FillStyleのpropertyはSolidに設定のこと//コマンドでは設定できない!! if(InputPacketBuffer[3] == 0x30) // オンか? { SwLamp_ovalShape->FillColor = Color::Orange; //ON ならオレンジ色 OnSw_pictureBox->Visible = true; //SW オン画像表示 OffSw_pictureBox->Visible = false; } else { SwLamp_ovalShape->FillColor = Color::Gray; // OFFなら灰色 OnSw_pictureBox->Visible = false; OffSw_pictureBox->Visible = true; //SW オフ画像表示 } //可変抵抗器出力電圧のAD変換値 読込 OutputPacketBuffer[0] = 0; // Report ID OutputPacketBuffer[1] = 0x82; // 可変抵抗器outのAD変換値読込 OutputPacketBuffer[2] = 0x31; // VR1 WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0); //対応するエンドポイント //InputPacketBuffer[3](Windows側)vs ToSendDataBuffer[2](PIC側) //InputPacketBuffer[4](Windows側)vs ToSendDataBuffer[3](PIC側) ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0); ADCValue = (InputPacketBuffer[4] * 256) + InputPacketBuffer[3]; Volt = (ADCValue * 3.3) / 4096; VR_textBox->Text = String::Format("{0:F2}",Volt); //小数点以下2桁にして表示 //四捨五入 temp = int((((float)ADCValue * 100) / 4096) + 0.5); //0.5を足して、小数点以下を切り捨てる VR_progressBar->Value = temp; } private: System::Void OnSw_pictureBox_Click(System::Object^ sender, System::EventArgs^ e) { } private: System::Void ovalShape1_Click(System::Object^ sender, System::EventArgs^ e) { } private: System::Void groupBox2_Enter(System::Object^ sender, System::EventArgs^ e) { } private: System::Void label4_Click(System::Object^ sender, System::EventArgs^ e) { } }; }
 




 
<動作結果> (→ 動画:1080pのHD動画を見ることができます。)

 モード PC画面 & PIC32MZ評価ボード 備考(部分拡大、詳細)
@ PCの後、PICを起動した状態の写真です。
 USBは未接続の状態です。
A 接続ボタンをクリックしてUSB通信が確立した状態です。
 スイッチのON/OFF状態や可変抵抗器の電圧はリアルタイムモニタリングされています。
   
B 接続ボタンをクリックして LEDのON/OFFボタンをクリックすることによって、PIC側のLEDを点灯させた状態です。 ON/OFFボタンスイッチが灰色→赤色に変化して、ランプの画像がOFFの画像からONの画像に変わっています。
 尚、スイッチはOFF、可変抵抗器の電圧は0vであることをモニタリングしています。
 
C PIC側のスイッチを押した状態です。シェープの色がオレンジ色になって、スイッチがONの画像が表示されています。  
D PIC側の可変抵抗器を回して、入力電圧が約1.2vの状態の写真です。 入力電圧のテキストボックスには1.21 [V]が表示され、またプログレスバーは、 36.7 (= 1.21/3.3) %を示しています。
  
 
E PICの電源をOFFにした状態です。 USB通信が遮断されたことを検出して PCのダイアログウィンドウはUSB通信が確立していない状態になっています。  

■ PIC32MZ2048EFH100
      CDCクラス 文字列送受信
                    (サンプルプログラム(VC++プロジェクトファイル) → ダウンロード
                      (サンプルプログラム(実行ファイル) → ダウンロード

                                   


★ PIC側のハードとソフトは、以下を参照願います

グラフィック液晶の
  ラベルウィジェットへの表示   
  プログラム名称     URL  
 有 ラベルにPCからのUSB受信文字列を表示
 URL
 無  USB(デバイスモード)CDCクラスPIC−PC間
文字列送受信
URL



<仕様>
 ・PCとPIC32MZ間でUSB接続による文字列の送受信をおこなう。
 ・USBのライブラリはHarmonyのCDCクラスをつかうこと
 ・PC側から文字列に対して PIC側からそれぞれに対応した文字列を返信すること
  送受信の文字列は 以下とする

      PCからの送信文字列 PICからの返信文字列
Japan\r Tokyo 
America\r Washington
U.K.\r  London
France\r  Paris
How are you?\ Pardon?

 ・PICのキャラくタ液晶はI2Cインターフェースのキャラクタ液晶とし、以下を表示のこと。
   1行目 …… PCからの受信文字列
   2行目 …… PCへの送信文字列

 ・PC側のアプリケーションは マイクロソフトのVC#で作成のこと。
 ・PCのアプリケーションプログラムの基本動作は、以下とする。
   尚、USBコネクタの脱着を検出し USB接続状態表示(接続完了/未接続 及びランプ表示の灰色/オレンジ色)に反映のこと。

操作/動作 @プログラム立ち上がり後の初期状態
  USB未接続状態、 
A接続ボタンをPC使用可能COMポートを検索し、使用COMポートのコンボボックスにセットする。セレクトされたCOMポートがPIC側とUSB接続できない場合は COMポート変更等を促すメッセージを表示する。 Bコンボボックスから別のCOMポートを選択する。
PC画面
操作/動作 CPIC側と接続できたCOMポートを選択できた場合は準備完了"I am Ready"のメッセージを表示する。 またこれと同時に送信ボタン、送信データ用のコンボボックス、"接続完了"の文字 及びオレンジ色のランプ表示も行う。 D送信データをコンボボックスから選択後、送信ボタンをクリックしてPIC側に送信する。PIC側からの返信データを受信データ用のリッチテキストボックスに表示する。
 尚、表示された受信データはクリアボタンで消去できること。
E停止ボタンをクリックするとUSB接続は遮断されること。 これに伴い使用COMポートは空欄となり、"未接続"の文字が表示されランプ表示は灰色となること。
PC画面


以下、プログラム抜粋

//Form1.h デザイン
//Form1.h
#pragma once

namespace CWhiteForm {

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;

using namespace System::Text; //Encoding^用
using namespace System::Security::Permissions; //[SecurityPermission(SecurityAction::Demand, Flags = SecurityPermissionFlag::UnmanagedCode)]
using namespace System::IO::Ports; //SerialPort::GetPortNames();



int OK_COM = 0; //COMポート接続完了フラグ
bool LampCOM = false; //COM/USB 接続表示
bool PerformClick = false; //偽クリック発生 //ピクチャーボックス再描画
bool RichTextBoxWritable = false; //リッチテキストボックス書き込み禁止(許可)

enum WINDOW_MESSAGES
{
WM_DEVICECHANGE = 0x0219,
}uint;

enum DBT
{
DBT_DEVICEARRIVAL = 0x8000,
DBT_DEVICEQUERYREMOVE = 0x8001,
DBT_DEVICEQUERYREMOVEFAILED = 0x8002,
DBT_DEVICEREMOVEPENDING = 0x8003,
DBT_DEVICEREMOVECOMPLETE = 0x8004,
};

/// <summary>
/// Form1 の概要
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: ここにコンストラクター コードを追加します
//
SendDataCBox->Items->Clear();
SendDataCBox->Items->Add("Japan");
SendDataCBox->Items->Add("America");
SendDataCBox->Items->Add("U.K.");
SendDataCBox->Items->Add("France");
SendDataCBox->Items->Add("How are you ?");
SendDataCBox->SelectedIndex = 0;

SendDataBtn->Visible = false;
SendDataCBox->Visible = false;
SendDataLabel->Visible = false;
}



[SecurityPermission(SecurityAction::Demand, Flags = SecurityPermissionFlag::UnmanagedCode)]
virtual void WndProc(Message% m)override
{
switch ((WINDOW_MESSAGES)m.Msg)
{
case WM_DEVICECHANGE:
// pnpEvent(this, EventArgs.Empty);

switch ((DBT)m.WParam.ToInt32())
{
case DBT_DEVICEARRIVAL:
//ドライブが装着された時の処理を書く
LampCOM = true;
ConnectLabel->Text = "接続完了";
PerformClick = true; //クリックによるリッチテキストクリア動作を無効化
ClearBtn->PerformClick(); //イベントを発生させ、Form1_Paint()を実行して描画を行う。
PerformClick = false; //クリックによるリッチテキストクリア動作を有効化
RichTextBoxWritable = true; //リッチテキストボックス書き込み許可
break;
case DBT_DEVICEREMOVECOMPLETE:
//ドライブが取り外されたされた時の処理を書く
LampCOM = false;
ConnectLabel->Text = "未接続";
RichTextBoxWritable = false; //リッチテキストボックス書き込み禁止
break;
}
break;
}
Form::WndProc(m);
}


protected:
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::Button^ ConnectBtn;
private: System::Windows::Forms::ComboBox^ ComCBox;
protected:

protected:

private: System::Windows::Forms::Label^ ConnectLabel1;


private: System::Windows::Forms::Label^ label2;
private: System::Windows::Forms::Button^ SendDataBtn;

private: System::Windows::Forms::ComboBox^ SendDataCBox;
private: System::Windows::Forms::Button^ ClearBtn;


private: System::Windows::Forms::RichTextBox^ richTextBox1;
private: System::Windows::Forms::Label^ ConnectLabel;

private: System::Windows::Forms::Label^ SendDataLabel;

private: System::IO::Ports::SerialPort^ serialPort1;
private: System::Windows::Forms::PictureBox^ pictureBox1;
private: System::Windows::Forms::Label^ label1;
private: System::Windows::Forms::Label^ label3;
private: System::Windows::Forms::Label^ label4;
private: System::ComponentModel::IContainer^ components;


protected:

protected:


private:
/// <summary>
/// 必要なデザイナー変数です。
/// </summary>


#pragma region Windows Form Designer generated code
/// <summary>
/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
/// コード エディターで変更しないでください。
/// </summary>
void InitializeComponent(void)
{
this->components = (gcnew System::ComponentModel::Container());
this->ConnectBtn = (gcnew System::Windows::Forms::Button());
this->ComCBox = (gcnew System::Windows::Forms::ComboBox());
this->ConnectLabel1 = (gcnew System::Windows::Forms::Label());
this->label2 = (gcnew System::Windows::Forms::Label());
this->SendDataBtn = (gcnew System::Windows::Forms::Button());
this->SendDataCBox = (gcnew System::Windows::Forms::ComboBox());
this->ClearBtn = (gcnew System::Windows::Forms::Button());
this->richTextBox1 = (gcnew System::Windows::Forms::RichTextBox());
this->ConnectLabel = (gcnew System::Windows::Forms::Label());
this->SendDataLabel = (gcnew System::Windows::Forms::Label());
this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
this->pictureBox1 = (gcnew System::Windows::Forms::PictureBox());
this->label1 = (gcnew System::Windows::Forms::Label());
this->label3 = (gcnew System::Windows::Forms::Label());
this->label4 = (gcnew System::Windows::Forms::Label());
(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->pictureBox1))->BeginInit();
this->SuspendLayout();
//
// ConnectBtn
//
this->ConnectBtn->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(128)));
this->ConnectBtn->Location = System::Drawing::Point(21, 42);
this->ConnectBtn->Name = L"ConnectBtn";
this->ConnectBtn->Size = System::Drawing::Size(83, 35);
this->ConnectBtn->TabIndex = 0;
this->ConnectBtn->Text = L"接続";
this->ConnectBtn->UseVisualStyleBackColor = true;
this->ConnectBtn->Click += gcnew System::EventHandler(this, &Form1::ConnectBtn_Click);
//
// ComCBox
//
this->ComCBox->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(128)));
this->ComCBox->FormattingEnabled = true;
this->ComCBox->Location = System::Drawing::Point(135, 50);
this->ComCBox->Name = L"ComCBox";
this->ComCBox->Size = System::Drawing::Size(115, 27);
this->ComCBox->TabIndex = 1;
this->ComCBox->TextChanged += gcnew System::EventHandler(this, &Form1::ComCBox_TextChanged);
//
// ConnectLabel1
//
this->ConnectLabel1->AutoSize = true;
this->ConnectLabel1->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(128)));
this->ConnectLabel1->Location = System::Drawing::Point(17, 20);
this->ConnectLabel1->Name = L"ConnectLabel1";
this->ConnectLabel1->Size = System::Drawing::Size(87, 19);
this->ConnectLabel1->TabIndex = 2;
this->ConnectLabel1->Text = L"USB接続";
//
// label2
//
this->label2->AutoSize = true;
this->label2->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(128)));
this->label2->Location = System::Drawing::Point(131, 20);
this->label2->Name = L"label2";
this->label2->Size = System::Drawing::Size(140, 19);
this->label2->TabIndex = 3;
this->label2->Text = L"使用COMポート";
//
// SendDataBtn
//
this->SendDataBtn->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(128)));
this->SendDataBtn->Location = System::Drawing::Point(21, 146);
this->SendDataBtn->Name = L"SendDataBtn";
this->SendDataBtn->Size = System::Drawing::Size(83, 35);
this->SendDataBtn->TabIndex = 4;
this->SendDataBtn->Text = L"送信";
this->SendDataBtn->UseVisualStyleBackColor = true;
this->SendDataBtn->Click += gcnew System::EventHandler(this, &Form1::SendDataBtn_Click);
//
// SendDataCBox
//
this->SendDataCBox->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(128)));
this->SendDataCBox->FormattingEnabled = true;
this->SendDataCBox->Location = System::Drawing::Point(21, 187);
this->SendDataCBox->Name = L"SendDataCBox";
this->SendDataCBox->Size = System::Drawing::Size(186, 27);
this->SendDataCBox->TabIndex = 5;
//
// ClearBtn
//
this->ClearBtn->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(128)));
this->ClearBtn->Location = System::Drawing::Point(373, 122);
this->ClearBtn->Name = L"ClearBtn";
this->ClearBtn->Size = System::Drawing::Size(83, 29);
this->ClearBtn->TabIndex = 6;
this->ClearBtn->Text = L"クリア";
this->ClearBtn->UseVisualStyleBackColor = true;
this->ClearBtn->Click += gcnew System::EventHandler(this, &Form1::ClearBtn_Click);
//
// richTextBox1
//
this->richTextBox1->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(128)));
this->richTextBox1->Location = System::Drawing::Point(279, 157);
this->richTextBox1->Name = L"richTextBox1";
this->richTextBox1->Size = System::Drawing::Size(177, 217);
this->richTextBox1->TabIndex = 7;
this->richTextBox1->Text = L"";
//
// ConnectLabel
//
this->ConnectLabel->AutoSize = true;
this->ConnectLabel->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(128)));
this->ConnectLabel->Location = System::Drawing::Point(275, 50);
this->ConnectLabel->Name = L"ConnectLabel";
this->ConnectLabel->Size = System::Drawing::Size(69, 19);
this->ConnectLabel->TabIndex = 8;
this->ConnectLabel->Text = L"未接続";
//
// SendDataLabel
//
this->SendDataLabel->AutoSize = true;
this->SendDataLabel->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(128)));
this->SendDataLabel->Location = System::Drawing::Point(110, 157);
this->SendDataLabel->Name = L"SendDataLabel";
this->SendDataLabel->Size = System::Drawing::Size(97, 19);
this->SendDataLabel->TabIndex = 9;
this->SendDataLabel->Text = L"送信データ";
//
// serialPort1
//
this->serialPort1->DataReceived += gcnew System::IO::Ports::SerialDataReceivedEventHandler(this, &Form1::serialPort1_DataReceived);
//
// pictureBox1
//
this->pictureBox1->Location = System::Drawing::Point(362, 26);
this->pictureBox1->Name = L"pictureBox1";
this->pictureBox1->Size = System::Drawing::Size(93, 66);
this->pictureBox1->TabIndex = 10;
this->pictureBox1->TabStop = false;
//
// label1
//
this->label1->AutoSize = true;
this->label1->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(128)));
this->label1->Location = System::Drawing::Point(275, 127);
this->label1->Name = L"label1";
this->label1->Size = System::Drawing::Size(97, 19);
this->label1->TabIndex = 11;
this->label1->Text = L"受信データ";
//
// label3
//
this->label3->AutoSize = true;
this->label3->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 12, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(128)));
this->label3->Location = System::Drawing::Point(53, 336);
this->label3->Name = L"label3";
this->label3->Size = System::Drawing::Size(113, 16);
this->label3->TabIndex = 12;
this->label3->Text = L"PC側プログラム";
//
// label4
//
this->label4->AutoSize = true;
this->label4->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 14.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(128)));
this->label4->Location = System::Drawing::Point(101, 355);
this->label4->Name = L"label4";
this->label4->Size = System::Drawing::Size(85, 19);
this->label4->TabIndex = 13;
this->label4->Text = L"VC++ 版";
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(482, 381);
this->Controls->Add(this->label4);
this->Controls->Add(this->label3);
this->Controls->Add(this->label1);
this->Controls->Add(this->pictureBox1);
this->Controls->Add(this->SendDataLabel);
this->Controls->Add(this->ConnectLabel);
this->Controls->Add(this->richTextBox1);
this->Controls->Add(this->ClearBtn);
this->Controls->Add(this->SendDataCBox);
this->Controls->Add(this->SendDataBtn);
this->Controls->Add(this->label2);
this->Controls->Add(this->ConnectLabel1);
this->Controls->Add(this->ComCBox);
this->Controls->Add(this->ConnectBtn);
this->Margin = System::Windows::Forms::Padding(2);
this->Name = L"Form1";
this->Text = L"Form1";
this->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &Form1::Form1_Paint);
(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->pictureBox1))->EndInit();
this->ResumeLayout(false);
this->PerformLayout();

}
#pragma endregion
private: System::Void Form1_Paint(System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e) //イベント発生時再描画
{
if (LampCOM == false)
{
Graphics^ g = pictureBox1->CreateGraphics(); //CreateGraphicsメソッドによりGraphicsオブジェクトを取得
SolidBrush^ br = gcnew SolidBrush(Color::Gray); //灰色ブラシ
g->FillEllipse(br, 10, 0, 50, 50); //灰色塗りつぶし 基点(10,0) 幅×高さ:50×50
}
else
{
Graphics^ g = pictureBox1->CreateGraphics(); //CreateGraphicsメソッドによりGraphicsオブジェクトを取得
SolidBrush^ br = gcnew SolidBrush(Color::Orange); //灰色ブラシ
g->FillEllipse(br, 10, 0, 50, 50);//橙色塗りつぶし 基点(10,0) 幅×高さ:50×50
}
}



delegate void ReceiveDelegate(String^ str);//デリゲート宣言


private: void SetText(String^ str)
{
if (RichTextBoxWritable == true) //リッチテキストボックス書き込み許可の場合
{
richTextBox1->AppendText(str); //文字列追加
richTextBox1->AppendText("\n"); //改行

}
}


private: void ComPortConnectTry() //COMポート接続チェック
{


//文字を変換するクラスを宣言
Encoding^ encSjis = Encoding::GetEncoding("shift-jis");
Encoding^ encUni = Encoding::GetEncoding("unicode");




try
{
serialPort1->DiscardInBuffer(); //受信バッファのデータクリア

String^ strSend = "Are you Ready ?";
if (!strSend->EndsWith("\r")) strSend += "\r"; //改行が無かったら \rを追加する
array<Byte>^byteArry = encSjis->GetBytes(strSend); //'送信文字をShift-jisに変換してをByte配列に格納
serialPort1->Write(byteArry, 0, byteArry->Length); //送信

String^ OK_message = "I am Ready\r\n";
String^ Response = serialPort1->ReadLine(); //返信データ抜き取り
OK_COM = OK_message->CompareTo(Response); //返信データが "I am Ready\r\n"の場合 1 を返す
if (OK_COM == 1)
{
ConnectLabel->Text = "接続完了";
SendDataBtn->Visible = true;
SendDataCBox->Visible = true;
SendDataLabel->Visible = true;

LampCOM = true;
ConnectBtn->Enabled = true;

}
MessageBox::Show(Response);
RichTextBoxWritable = true;

}

catch (TimeoutException^ ex2)
{
OK_COM = 0;
ConnectLabel->Text = "未接続";
SendDataBtn->Visible = false;
SendDataCBox->Visible = false;
SendDataLabel->Visible = false;

LampCOM = false;
ConnectBtn->Enabled = false;
RichTextBoxWritable = false; //リッチテキストボックス書き込み禁止

String^ TimeoutStr = "1. COMポートをかえてみてください \n2. COMポートコネクタの抜けなど断線がないチェックしてください。";
MessageBox::Show(ex2->Message + "\n" + TimeoutStr);
}

}





private: System::Void ConnectBtn_Click(System::Object^ sender, System::EventArgs^ e)
{

if (ConnectBtn->Text == "停止")
{
serialPort1->Close();//シリアルポートオープン
ConnectBtn->Text = "接続";
SendDataBtn->Visible = false;
SendDataCBox->Visible = false;
SendDataLabel->Visible = false;
ConnectLabel->Text = "未接続";
LampCOM = false;
ComCBox->Items->Clear();
ComCBox->Text = "";

return;
}


if (ConnectBtn->Enabled == true) ConnectBtn->Text = "停止";
else ConnectBtn->Text = "接続";


array<String^>^ PortList = nullptr;

PortList = SerialPort::GetPortNames();


try
{
ComCBox->Items->Clear();


//シリアルポート名をコンボボックスにセット
for each(String^ PortName in PortList) //VC++ foreach(VC#) → for each(VC++)
{
ComCBox->Items->Add(PortName);
}

if (ComCBox->Items->Count > 0)
{
ComCBox->SelectedIndex = 0;
}

serialPort1->PortName = ComCBox->SelectedItem->ToString();
serialPort1->BaudRate = 9600; //9600bps
serialPort1->Parity = Parity::None; //パリティなし
serialPort1->DataBits = 8; //データ長 8ビット
serialPort1->StopBits = StopBits::One; //ストップビット 1
serialPort1->ReadTimeout = 500; //500mse 読み込みタイムアウト時間
serialPort1->WriteTimeout = 500; //500msec書き込みタイムアウト時間

serialPort1->Open();//シリアルポートオープン

}
catch (Exception^ ex)
{
System::Windows::Forms::DialogResult result = MessageBox::Show
(ex->Message + "\n" + "COMポートがひらけません55");
}

ComPortConnectTry(); //COMポート接続チェック

}


private: System::Void ClearBtn_Click(System::Object^ sender, System::EventArgs^ e)
{
if (PerformClick == false)richTextBox1->Clear(); //マウスでの実際のクリックが発生した場合のみ リッチテキストクリア
}



private: System::Void serialPort1_DataReceived(System::Object^ sender, System::IO::Ports::SerialDataReceivedEventArgs^ e)
{

//文字を変換するクラスを宣言
Encoding^ encSjis = Encoding::GetEncoding("shift-jis");
Encoding^ encUni = Encoding::GetEncoding("unicode");


array<Byte>^byteRead = gcnew array<Byte>(serialPort1->BytesToRead); //受信文字
// byte[] byteRead = new byte[serialPort1.BytesToRead]; //受信文字

serialPort1->Read(byteRead, 0, serialPort1->BytesToRead);//読み込み
array<Byte>^ byteUni = Encoding::Convert(encSjis, encUni, byteRead); //shift-jis からunicodeに変換する
String^ strUni = encUni->GetString(byteUni); //配列を文字列に変換

// シリアルポートの受信イベントはフォームが作成された時のスレッドとは別のスレッドで動作しますので、
//メインの Form上のコンポーネントを変更する必要がある場合は、Invoke を経由してして変更します。
ReceiveDelegate^ receiveDelegate = gcnew ReceiveDelegate(this, &CWhiteForm::Form1::SetText); //
this->Invoke(receiveDelegate, strUni);
}

private: System::Void ComCBox_TextChanged(System::Object^ sender, System::EventArgs^ e)
{
if (serialPort1->IsOpen == true)
{
serialPort1->Close();//シリアルポートクローズ

serialPort1->PortName = ComCBox->SelectedItem->ToString();
serialPort1->BaudRate = 9600; //9600bps
serialPort1->Parity = Parity::None; //パリティなし
serialPort1->DataBits = 8; //データ長 8ビット
serialPort1->StopBits = StopBits::One; //ストップビット 1
serialPort1->ReadTimeout = 500; //500mse 読み込みタイムアウト時間
serialPort1->WriteTimeout = 500; //500msec書き込みタイムアウト時間

serialPort1->Open();//シリアルポートオープン

ComPortConnectTry(); //COMポート接続チェック
}
}
private: System::Void SendDataBtn_Click(System::Object^ sender, System::EventArgs^ e)
{
//文字を変換するクラスを宣言
Encoding^ encSjis = Encoding::GetEncoding("shift-jis");
Encoding^ encUni = Encoding::GetEncoding("unicode");

try
{
if (serialPort1->IsOpen == false) serialPort1->Open();//シリアルポートオープン

serialPort1->DiscardInBuffer(); //受信バッファのデータクリア

String^ strSend = SendDataCBox->Text;
if (!strSend->EndsWith("\r")) strSend += "\r"; //改行が無かったら \rを追加する
array<Byte>^ byteArry = encSjis->GetBytes(strSend); //'送信文字をShift-jisに変換してをByte配列に格納
serialPort1->Write(byteArry, 0, byteArry->Length); //送信
}
catch (Exception^ ex)
{
System::Windows::Forms::DialogResult result = MessageBox::Show
(ex->Message + "\n" + "COMポートがひらけません");
}
}


};
}

 



<動作結果>(→ 動画:1080pのHD動画を見ることができます。)

操作/動作 PC画面 & PIC32MZ評価ボード 備考
@プログラム立ち上がり後の初期状態
  USB未接続状態
A接続ボタンをPC使用可能COMポートを検索し、使用COMポートのコンボボックスにセットする。セレクトされたCOMポートがPIC側とUSB接続できない場合は COMポート変更等を促すメッセージを表示する。
Bコンボボックスから別のCOMポートを選択する。
CPIC側と接続できたCOMポートを選択できた場合は準備完了"I am Ready"のメッセージを表示する。 またこれと同時に送信ボタン、送信データ用のコンボボックス、"接続完了"の文字 及びオレンジ色のランプ表示も行う。
D送信データをコンボボックスから選択後、送信ボタンをクリックしてPIC側に送信する。PIC側からの返信データを受信データ用のリッチテキストボックスに表示する。
 尚、表示された受信データはクリアボタンで消去できること。
E停止ボタンをクリックするとUSB接続は遮断されること。 これに伴い使用COMポートは空欄となり、"未接続"の文字が表示されランプ表示は灰色となること。